/*
 * lesamnta_opt32.c
 *
 * Copyright (C) 2008 Hitachi, Ltd., All rights reserved.
 * Systems Development Laboratory, Hitachi, Ltd.
 */

#include <string.h>  /* for memset(), memcopy() */
#include "lesamnta.h"

# define BYTES_SWAP32(x)\
	((x << 24) | ((x & 0x0000ff00) << 8) | ((x & 0x00ff0000) >> 8) | (x >> 24))

/* BYTES_SWAP256(x) stores each 32-bit word of 256 bits data in little-endian convention */
#define BYTES_SWAP256(x) { \
	int _i = 8; while(_i--){x[_i] = BYTES_SWAP32(x[_i]);} \
}

/* BYTES_SWAP512(x) stores each 64-bit word of 512 bits data in little-endian convention */
#define BYTES_SWAP512(x) { \
	int _i = 16; while(_i--){x[_i] = BYTES_SWAP32(x[_i]);} \
}

#define ST224(x) (x->state.state256)
#define ST256(x) (x->state.state256)
#define ST384(x) (x->state.state512)
#define ST512(x) (x->state.state512)


#define ROUND256(a,b,c,d) \
	tmp.msg[0] = midmsg[a]     ^ midkey[b]; \
	tmp.msg[1] = midmsg[a + 1] ^ midkey[b + 1]; \
	tmp.key[0] = midkey[a] ^ (u32)CNS[d][0]; \
	tmp.key[1] = midkey[a + 1] ^ (u32)CNS[d][1]; \
	F256_1(tmp.key,tmp.t); \
	midkey[c]     ^= tmp.key[0]; \
	midkey[c + 1] ^= tmp.key[1]; \
	F256_2(tmp.msg, tmp.t); \
	midmsg[c]     ^= tmp.msg[0]; \
	midmsg[c + 1] ^= tmp.msg[1]; 

#define ROUND256_OUTPUT(a,b,c,d) \
	tmp.msg[0] = midmsg[a]     ^ midkey[b]; \
	tmp.msg[1] = midmsg[a + 1] ^ midkey[b + 1]; \
	tmp.key[0] = midkey[a] ^ (u32)CNS[d][0]; \
	tmp.key[1] = midkey[a + 1] ^ (u32)CNS[d][1]; \
	F256_2(tmp.key, tmp.t); \
	midkey[c]     ^= tmp.key[0]; \
	midkey[c + 1] ^= tmp.key[1]; \
	F256_2(tmp.msg, tmp.t); \
	midmsg[c]     ^= tmp.msg[0]; \
	midmsg[c + 1] ^= tmp.msg[1];

#define F256_1(s, t) \
	t[0] =  TBLB0[(s[0] >> 24)       ]; \
	t[0] ^= TBLB1[(s[0] >> 16) & 0xff]; \
	t[0] ^= TBLB2[(s[0] >>  8) & 0xff]; \
	t[0] ^= TBLB3[(s[0]      ) & 0xff]; \
	t[1] =  TBLB0[(s[1] >> 24)       ]; \
	t[1] ^= TBLB1[(s[1] >> 16) & 0xff]; \
	t[1] ^= TBLB2[(s[1] >>  8) & 0xff]; \
	t[1] ^= TBLB3[(s[1]      ) & 0xff]; \
	s[0] = (t[0] & 0xffff) | (t[1] & 0xffff0000); \
	s[1] = (t[1] & 0xffff) | (t[0] & 0xffff0000); 

#define F256_2(s, t) \
	t[0] = TBLA0[s[0] >> 24] ^ TBLA1[s[0] & 0xff] ^ TBLA2[(s[0] >> 8) & 0xff] ^ TBLA3[(s[1] >> 16) & 0xff]; \
	t[1] = TBLA0[s[1] >> 24] ^ TBLA1[s[1] & 0xff] ^ TBLA2[(s[1] >> 8) & 0xff] ^ TBLA3[(s[0] >> 16) & 0xff]; \
	s[0] = TBLA0[t[0] >> 24] ^ TBLA1[t[0] & 0xff] ^ TBLA2[(t[0] >> 8) & 0xff] ^ TBLA3[(t[1] >> 16) & 0xff]; \
	s[1] = TBLA0[t[1] >> 24] ^ TBLA1[t[1] & 0xff] ^ TBLA2[(t[1] >> 8) & 0xff] ^ TBLA3[(t[0] >> 16) & 0xff]; \
	t[0] = TBLA0[s[0] >> 24] ^ TBLA1[s[0] & 0xff] ^ TBLA2[(s[0] >> 8) & 0xff] ^ TBLA3[(s[1] >> 16) & 0xff]; \
	t[1] = TBLA0[s[1] >> 24] ^ TBLA1[s[1] & 0xff] ^ TBLA2[(s[1] >> 8) & 0xff] ^ TBLA3[(s[0] >> 16) & 0xff]; \
	s[0] = TBLA0[t[0] >> 24] ^ TBLA1[t[0] & 0xff] ^ TBLA2[(t[0] >> 8) & 0xff] ^ TBLA3[(t[1] >> 16) & 0xff]; \
	s[1] = TBLA0[t[1] >> 24] ^ TBLA1[t[1] & 0xff] ^ TBLA2[(t[1] >> 8) & 0xff] ^ TBLA3[(t[0] >> 16) & 0xff];

#define ROUND512(a, b, c, d) \
	tmp.key[0] = midkey[a]; \
	tmp.key[1] = midkey[a + 1] ^ (u32)CNS[d][0]; \
	tmp.key[2] = midkey[a + 2]; \
	tmp.key[3] = midkey[a + 3] ^ (u32)CNS[d][1]; \
	F512_1(tmp.key, midkey, c); \
	tmp.msg[0] = midmsg[a]     ^ midkey[b]; \
	tmp.msg[1] = midmsg[a + 1] ^ midkey[b + 1]; \
	tmp.msg[2] = midmsg[a + 2] ^ midkey[b + 2]; \
	tmp.msg[3] = midmsg[a + 3] ^ midkey[b + 3]; \
	F512_2(tmp.msg, tmp.t); \
	midmsg[c]     ^= tmp.msg[0]; \
	midmsg[c + 1] ^= tmp.msg[1]; \
	midmsg[c + 2] ^= tmp.msg[2]; \
	midmsg[c + 3] ^= tmp.msg[3]; 

#define ROUND512_OUTPUT(a, b, c, d) \
	tmp.key[0] = midkey[a]; \
	tmp.key[1] = midkey[a + 1] ^ (u32)CNS[d][0]; \
	tmp.key[2] = midkey[a + 2]; \
	tmp.key[3] = midkey[a + 3] ^ (u32)CNS[d][1]; \
	F512_2(tmp.key, tmp.t); \
	midkey[c]     ^= tmp.key[0]; \
	midkey[c + 1] ^= tmp.key[1]; \
	midkey[c + 2] ^= tmp.key[2]; \
	midkey[c + 3] ^= tmp.key[3]; \
	tmp.msg[0] = midmsg[a]     ^ midkey[b]; \
	tmp.msg[1] = midmsg[a + 1] ^ midkey[b + 1]; \
	tmp.msg[2] = midmsg[a + 2] ^ midkey[b + 2]; \
	tmp.msg[3] = midmsg[a + 3] ^ midkey[b + 3]; \
	F512_2(tmp.msg, tmp.t); \
	midmsg[c]     ^= tmp.msg[0]; \
	midmsg[c + 1] ^= tmp.msg[1]; \
	midmsg[c + 2] ^= tmp.msg[2]; \
	midmsg[c + 3] ^= tmp.msg[3];

#define F512_1(s, r, i) \
	r[i + 2] ^= TBLC0[s[0] >> 24] ^ TBLC1[(s[0] >> 16) & 0xff] ^ TBLC2[(s[0] >> 8) & 0xff] ^ TBLC3[s[0] & 0xff] ^ \
	            TBLC4[s[1] >> 24] ^ TBLC5[(s[1] >> 16) & 0xff] ^ TBLC6[(s[1] >> 8) & 0xff] ^ TBLC7[s[1] & 0xff]; \
	r[i + 1] ^= TBLC4[s[0] >> 24] ^ TBLC5[(s[0] >> 16) & 0xff] ^ TBLC6[(s[0] >> 8) & 0xff] ^ TBLC7[s[0] & 0xff] ^ \
	            TBLC0[s[1] >> 24] ^ TBLC1[(s[1] >> 16) & 0xff] ^ TBLC2[(s[1] >> 8) & 0xff] ^ TBLC3[s[1] & 0xff]; \
	r[i]     ^= TBLC0[s[2] >> 24] ^ TBLC1[(s[2] >> 16) & 0xff] ^ TBLC2[(s[2] >> 8) & 0xff] ^ TBLC3[s[2] & 0xff] ^ \
	            TBLC4[s[3] >> 24] ^ TBLC5[(s[3] >> 16) & 0xff] ^ TBLC6[(s[3] >> 8) & 0xff] ^ TBLC7[s[3] & 0xff]; \
	r[i + 3] ^= TBLC4[s[2] >> 24] ^ TBLC5[(s[2] >> 16) & 0xff] ^ TBLC6[(s[2] >> 8) & 0xff] ^ TBLC7[s[2] & 0xff] ^ \
	            TBLC0[s[3] >> 24] ^ TBLC1[(s[3] >> 16) & 0xff] ^ TBLC2[(s[3] >> 8) & 0xff] ^ TBLC3[s[3] & 0xff]; 

#define F512_2(s, t) \
	t[0] = TBLB0[s[0] >> 24] ^ TBLB1[(s[1] >> 16) & 0xff] ^ TBLB2[(s[2] >> 8) & 0xff] ^ TBLB3[(s[3]) & 0xff]; \
	t[1] = TBLB0[s[1] >> 24] ^ TBLB1[(s[2] >> 16) & 0xff] ^ TBLB2[(s[3] >> 8) & 0xff] ^ TBLB3[(s[0]) & 0xff]; \
	t[2] = TBLB0[s[2] >> 24] ^ TBLB1[(s[3] >> 16) & 0xff] ^ TBLB2[(s[0] >> 8) & 0xff] ^ TBLB3[(s[1]) & 0xff]; \
	t[3] = TBLB0[s[3] >> 24] ^ TBLB1[(s[0] >> 16) & 0xff] ^ TBLB2[(s[1] >> 8) & 0xff] ^ TBLB3[(s[2]) & 0xff]; \
	s[0] = TBLB0[t[0] >> 24] ^ TBLB1[(t[1] >> 16) & 0xff] ^ TBLB2[(t[2] >> 8) & 0xff] ^ TBLB3[(t[3]) & 0xff]; \
	s[1] = TBLB0[t[1] >> 24] ^ TBLB1[(t[2] >> 16) & 0xff] ^ TBLB2[(t[3] >> 8) & 0xff] ^ TBLB3[(t[0]) & 0xff]; \
	s[2] = TBLB0[t[2] >> 24] ^ TBLB1[(t[3] >> 16) & 0xff] ^ TBLB2[(t[0] >> 8) & 0xff] ^ TBLB3[(t[1]) & 0xff]; \
	s[3] = TBLB0[t[3] >> 24] ^ TBLB1[(t[0] >> 16) & 0xff] ^ TBLB2[(t[1] >> 8) & 0xff] ^ TBLB3[(t[2]) & 0xff]; \
	t[0] = TBLB0[s[0] >> 24] ^ TBLB1[(s[1] >> 16) & 0xff] ^ TBLB2[(s[2] >> 8) & 0xff] ^ TBLB3[(s[3]) & 0xff]; \
	t[1] = TBLB0[s[1] >> 24] ^ TBLB1[(s[2] >> 16) & 0xff] ^ TBLB2[(s[3] >> 8) & 0xff] ^ TBLB3[(s[0]) & 0xff]; \
	t[2] = TBLB0[s[2] >> 24] ^ TBLB1[(s[3] >> 16) & 0xff] ^ TBLB2[(s[0] >> 8) & 0xff] ^ TBLB3[(s[1]) & 0xff]; \
	t[3] = TBLB0[s[3] >> 24] ^ TBLB1[(s[0] >> 16) & 0xff] ^ TBLB2[(s[1] >> 8) & 0xff] ^ TBLB3[(s[2]) & 0xff]; \
	s[0] = TBLB0[t[0] >> 24] ^ TBLB1[(t[1] >> 16) & 0xff] ^ TBLB2[(t[2] >> 8) & 0xff] ^ TBLB3[(t[3]) & 0xff]; \
	s[1] = TBLB0[t[1] >> 24] ^ TBLB1[(t[2] >> 16) & 0xff] ^ TBLB2[(t[3] >> 8) & 0xff] ^ TBLB3[(t[0]) & 0xff]; \
	s[2] = TBLB0[t[2] >> 24] ^ TBLB1[(t[3] >> 16) & 0xff] ^ TBLB2[(t[0] >> 8) & 0xff] ^ TBLB3[(t[1]) & 0xff]; \
	s[3] = TBLB0[t[3] >> 24] ^ TBLB1[(t[0] >> 16) & 0xff] ^ TBLB2[(t[1] >> 8) & 0xff] ^ TBLB3[(t[2]) & 0xff];

HashReturn Init256(hashState *state);
HashReturn Update256(hashState *state, const BitSequence *data, Datalength databitlen);
HashReturn Final256(hashState *state, BitSequence *hashval);

HashReturn Init512(hashState *state);
HashReturn Update512(hashState *state, const BitSequence *data, Datalength databitlen);
HashReturn Final512(hashState *state, BitSequence *hashval);

HashReturn Init224(hashState *state);
HashReturn Update224(hashState *state, const BitSequence *data, Datalength databitlen);
HashReturn Final224(hashState *state, BitSequence *hashval);

HashReturn Init384(hashState *state);
HashReturn Update384(hashState *state, const BitSequence *data, Datalength databitlen);
HashReturn Final384(hashState *state, BitSequence *hashval);

static void Output256(u32 *H, const u32 *M);
static void Compression256(u32 *H, const u32 *M);

static void Output512(u32 *H, const u32 *M);
static void Compression512(u32 *H, const u32 *M);

/* Initial hash velue of Lesamnta-224 */
static const u32 H_init224[8] = {
	0x00000224, 0x00000224, 0x00000224, 0x00000224, 
	0x00000224, 0x00000224, 0x00000224, 0x00000224
};

/* Initial hash velue of Lesamnta-256 */
static const u32 H_init256[8] = {
	0x00000256, 0x00000256, 0x00000256, 0x00000256, 
	0x00000256, 0x00000256, 0x00000256, 0x00000256
};

/* Initial hash velue of Lesamnta-384 */
static const u32 H_init384[16] = {
	0x00000000, 0x00000384, 0x00000000, 0x00000384, 
	0x00000000, 0x00000384, 0x00000000, 0x00000384, 
	0x00000000, 0x00000384, 0x00000000, 0x00000384, 
	0x00000000, 0x00000384, 0x00000000, 0x00000384
};

/* Initial hash velue of Lesamnta-512 */
static const u32 H_init512[16] = {
	0x00000000, 0x00000512, 0x00000000, 0x00000512, 
	0x00000000, 0x00000512, 0x00000000, 0x00000512, 
	0x00000000, 0x00000512, 0x00000000, 0x00000512, 
	0x00000000, 0x00000512, 0x00000000, 0x00000512
};

static const u32 TBLA0[256]={
	0xc6630000, 0xf87c0000, 0xee770000, 0xf67b0000, 
	0xfff20000, 0xd66b0000, 0xde6f0000, 0x91c50000, 
	0x60300000, 0x02010000, 0xce670000, 0x562b0000, 
	0xe7fe0000, 0xb5d70000, 0x4dab0000, 0xec760000, 
	0x8fca0000, 0x1f820000, 0x89c90000, 0xfa7d0000, 
	0xeffa0000, 0xb2590000, 0x8e470000, 0xfbf00000, 
	0x41ad0000, 0xb3d40000, 0x5fa20000, 0x45af0000, 
	0x239c0000, 0x53a40000, 0xe4720000, 0x9bc00000, 
	0x75b70000, 0xe1fd0000, 0x3d930000, 0x4c260000, 
	0x6c360000, 0x7e3f0000, 0xf5f70000, 0x83cc0000, 
	0x68340000, 0x51a50000, 0xd1e50000, 0xf9f10000, 
	0xe2710000, 0xabd80000, 0x62310000, 0x2a150000, 
	0x08040000, 0x95c70000, 0x46230000, 0x9dc30000, 
	0x30180000, 0x37960000, 0x0a050000, 0x2f9a0000, 
	0x0e070000, 0x24120000, 0x1b800000, 0xdfe20000, 
	0xcdeb0000, 0x4e270000, 0x7fb20000, 0xea750000, 
	0x12090000, 0x1d830000, 0x582c0000, 0x341a0000, 
	0x361b0000, 0xdc6e0000, 0xb45a0000, 0x5ba00000, 
	0xa4520000, 0x763b0000, 0xb7d60000, 0x7db30000, 
	0x52290000, 0xdde30000, 0x5e2f0000, 0x13840000, 
	0xa6530000, 0xb9d10000, 0x00000000, 0xc1ed0000, 
	0x40200000, 0xe3fc0000, 0x79b10000, 0xb65b0000, 
	0xd46a0000, 0x8dcb0000, 0x67be0000, 0x72390000, 
	0x944a0000, 0x984c0000, 0xb0580000, 0x85cf0000, 
	0xbbd00000, 0xc5ef0000, 0x4faa0000, 0xedfb0000, 
	0x86430000, 0x9a4d0000, 0x66330000, 0x11850000, 
	0x8a450000, 0xe9f90000, 0x04020000, 0xfe7f0000, 
	0xa0500000, 0x783c0000, 0x259f0000, 0x4ba80000, 
	0xa2510000, 0x5da30000, 0x80400000, 0x058f0000, 
	0x3f920000, 0x219d0000, 0x70380000, 0xf1f50000, 
	0x63bc0000, 0x77b60000, 0xafda0000, 0x42210000, 
	0x20100000, 0xe5ff0000, 0xfdf30000, 0xbfd20000, 
	0x81cd0000, 0x180c0000, 0x26130000, 0xc3ec0000, 
	0xbe5f0000, 0x35970000, 0x88440000, 0x2e170000, 
	0x93c40000, 0x55a70000, 0xfc7e0000, 0x7a3d0000, 
	0xc8640000, 0xba5d0000, 0x32190000, 0xe6730000, 
	0xc0600000, 0x19810000, 0x9e4f0000, 0xa3dc0000, 
	0x44220000, 0x542a0000, 0x3b900000, 0x0b880000, 
	0x8c460000, 0xc7ee0000, 0x6bb80000, 0x28140000, 
	0xa7de0000, 0xbc5e0000, 0x160b0000, 0xaddb0000, 
	0xdbe00000, 0x64320000, 0x743a0000, 0x140a0000, 
	0x92490000, 0x0c060000, 0x48240000, 0xb85c0000, 
	0x9fc20000, 0xbdd30000, 0x43ac0000, 0xc4620000, 
	0x39910000, 0x31950000, 0xd3e40000, 0xf2790000, 
	0xd5e70000, 0x8bc80000, 0x6e370000, 0xda6d0000, 
	0x018d0000, 0xb1d50000, 0x9c4e0000, 0x49a90000, 
	0xd86c0000, 0xac560000, 0xf3f40000, 0xcfea0000, 
	0xca650000, 0xf47a0000, 0x47ae0000, 0x10080000, 
	0x6fba0000, 0xf0780000, 0x4a250000, 0x5c2e0000, 
	0x381c0000, 0x57a60000, 0x73b40000, 0x97c60000, 
	0xcbe80000, 0xa1dd0000, 0xe8740000, 0x3e1f0000, 
	0x964b0000, 0x61bd0000, 0x0d8b0000, 0x0f8a0000, 
	0xe0700000, 0x7c3e0000, 0x71b50000, 0xcc660000, 
	0x90480000, 0x06030000, 0xf7f60000, 0x1c0e0000, 
	0xc2610000, 0x6a350000, 0xae570000, 0x69b90000, 
	0x17860000, 0x99c10000, 0x3a1d0000, 0x279e0000, 
	0xd9e10000, 0xebf80000, 0x2b980000, 0x22110000, 
	0xd2690000, 0xa9d90000, 0x078e0000, 0x33940000, 
	0x2d9b0000, 0x3c1e0000, 0x15870000, 0xc9e90000, 
	0x87ce0000, 0xaa550000, 0x50280000, 0xa5df0000, 
	0x038c0000, 0x59a10000, 0x09890000, 0x1a0d0000, 
	0x65bf0000, 0xd7e60000, 0x84420000, 0xd0680000, 
	0x82410000, 0x29990000, 0x5a2d0000, 0x1e0f0000, 
	0x7bb00000, 0xa8540000, 0x6dbb0000, 0x2c160000
};

static const u32 TBLA1[256]={
	0x63c60000, 0x7cf80000, 0x77ee0000, 0x7bf60000, 
	0xf2ff0000, 0x6bd60000, 0x6fde0000, 0xc5910000, 
	0x30600000, 0x01020000, 0x67ce0000, 0x2b560000, 
	0xfee70000, 0xd7b50000, 0xab4d0000, 0x76ec0000, 
	0xca8f0000, 0x821f0000, 0xc9890000, 0x7dfa0000, 
	0xfaef0000, 0x59b20000, 0x478e0000, 0xf0fb0000, 
	0xad410000, 0xd4b30000, 0xa25f0000, 0xaf450000, 
	0x9c230000, 0xa4530000, 0x72e40000, 0xc09b0000, 
	0xb7750000, 0xfde10000, 0x933d0000, 0x264c0000, 
	0x366c0000, 0x3f7e0000, 0xf7f50000, 0xcc830000, 
	0x34680000, 0xa5510000, 0xe5d10000, 0xf1f90000, 
	0x71e20000, 0xd8ab0000, 0x31620000, 0x152a0000, 
	0x04080000, 0xc7950000, 0x23460000, 0xc39d0000, 
	0x18300000, 0x96370000, 0x050a0000, 0x9a2f0000, 
	0x070e0000, 0x12240000, 0x801b0000, 0xe2df0000, 
	0xebcd0000, 0x274e0000, 0xb27f0000, 0x75ea0000, 
	0x09120000, 0x831d0000, 0x2c580000, 0x1a340000, 
	0x1b360000, 0x6edc0000, 0x5ab40000, 0xa05b0000, 
	0x52a40000, 0x3b760000, 0xd6b70000, 0xb37d0000, 
	0x29520000, 0xe3dd0000, 0x2f5e0000, 0x84130000, 
	0x53a60000, 0xd1b90000, 0x00000000, 0xedc10000, 
	0x20400000, 0xfce30000, 0xb1790000, 0x5bb60000, 
	0x6ad40000, 0xcb8d0000, 0xbe670000, 0x39720000, 
	0x4a940000, 0x4c980000, 0x58b00000, 0xcf850000, 
	0xd0bb0000, 0xefc50000, 0xaa4f0000, 0xfbed0000, 
	0x43860000, 0x4d9a0000, 0x33660000, 0x85110000, 
	0x458a0000, 0xf9e90000, 0x02040000, 0x7ffe0000, 
	0x50a00000, 0x3c780000, 0x9f250000, 0xa84b0000, 
	0x51a20000, 0xa35d0000, 0x40800000, 0x8f050000, 
	0x923f0000, 0x9d210000, 0x38700000, 0xf5f10000, 
	0xbc630000, 0xb6770000, 0xdaaf0000, 0x21420000, 
	0x10200000, 0xffe50000, 0xf3fd0000, 0xd2bf0000, 
	0xcd810000, 0x0c180000, 0x13260000, 0xecc30000, 
	0x5fbe0000, 0x97350000, 0x44880000, 0x172e0000, 
	0xc4930000, 0xa7550000, 0x7efc0000, 0x3d7a0000, 
	0x64c80000, 0x5dba0000, 0x19320000, 0x73e60000, 
	0x60c00000, 0x81190000, 0x4f9e0000, 0xdca30000, 
	0x22440000, 0x2a540000, 0x903b0000, 0x880b0000, 
	0x468c0000, 0xeec70000, 0xb86b0000, 0x14280000, 
	0xdea70000, 0x5ebc0000, 0x0b160000, 0xdbad0000, 
	0xe0db0000, 0x32640000, 0x3a740000, 0x0a140000, 
	0x49920000, 0x060c0000, 0x24480000, 0x5cb80000, 
	0xc29f0000, 0xd3bd0000, 0xac430000, 0x62c40000, 
	0x91390000, 0x95310000, 0xe4d30000, 0x79f20000, 
	0xe7d50000, 0xc88b0000, 0x376e0000, 0x6dda0000, 
	0x8d010000, 0xd5b10000, 0x4e9c0000, 0xa9490000, 
	0x6cd80000, 0x56ac0000, 0xf4f30000, 0xeacf0000, 
	0x65ca0000, 0x7af40000, 0xae470000, 0x08100000, 
	0xba6f0000, 0x78f00000, 0x254a0000, 0x2e5c0000, 
	0x1c380000, 0xa6570000, 0xb4730000, 0xc6970000, 
	0xe8cb0000, 0xdda10000, 0x74e80000, 0x1f3e0000, 
	0x4b960000, 0xbd610000, 0x8b0d0000, 0x8a0f0000, 
	0x70e00000, 0x3e7c0000, 0xb5710000, 0x66cc0000, 
	0x48900000, 0x03060000, 0xf6f70000, 0x0e1c0000, 
	0x61c20000, 0x356a0000, 0x57ae0000, 0xb9690000, 
	0x86170000, 0xc1990000, 0x1d3a0000, 0x9e270000, 
	0xe1d90000, 0xf8eb0000, 0x982b0000, 0x11220000, 
	0x69d20000, 0xd9a90000, 0x8e070000, 0x94330000, 
	0x9b2d0000, 0x1e3c0000, 0x87150000, 0xe9c90000, 
	0xce870000, 0x55aa0000, 0x28500000, 0xdfa50000, 
	0x8c030000, 0xa1590000, 0x89090000, 0x0d1a0000, 
	0xbf650000, 0xe6d70000, 0x42840000, 0x68d00000, 
	0x41820000, 0x99290000, 0x2d5a0000, 0x0f1e0000, 
	0xb07b0000, 0x54a80000, 0xbb6d0000, 0x162c0000
};

static const u32 TBLA2[256]={
	0x0000c663, 0x0000f87c, 0x0000ee77, 0x0000f67b, 
	0x0000fff2, 0x0000d66b, 0x0000de6f, 0x000091c5, 
	0x00006030, 0x00000201, 0x0000ce67, 0x0000562b, 
	0x0000e7fe, 0x0000b5d7, 0x00004dab, 0x0000ec76, 
	0x00008fca, 0x00001f82, 0x000089c9, 0x0000fa7d, 
	0x0000effa, 0x0000b259, 0x00008e47, 0x0000fbf0, 
	0x000041ad, 0x0000b3d4, 0x00005fa2, 0x000045af, 
	0x0000239c, 0x000053a4, 0x0000e472, 0x00009bc0, 
	0x000075b7, 0x0000e1fd, 0x00003d93, 0x00004c26, 
	0x00006c36, 0x00007e3f, 0x0000f5f7, 0x000083cc, 
	0x00006834, 0x000051a5, 0x0000d1e5, 0x0000f9f1, 
	0x0000e271, 0x0000abd8, 0x00006231, 0x00002a15, 
	0x00000804, 0x000095c7, 0x00004623, 0x00009dc3, 
	0x00003018, 0x00003796, 0x00000a05, 0x00002f9a, 
	0x00000e07, 0x00002412, 0x00001b80, 0x0000dfe2, 
	0x0000cdeb, 0x00004e27, 0x00007fb2, 0x0000ea75, 
	0x00001209, 0x00001d83, 0x0000582c, 0x0000341a, 
	0x0000361b, 0x0000dc6e, 0x0000b45a, 0x00005ba0, 
	0x0000a452, 0x0000763b, 0x0000b7d6, 0x00007db3, 
	0x00005229, 0x0000dde3, 0x00005e2f, 0x00001384, 
	0x0000a653, 0x0000b9d1, 0x00000000, 0x0000c1ed, 
	0x00004020, 0x0000e3fc, 0x000079b1, 0x0000b65b, 
	0x0000d46a, 0x00008dcb, 0x000067be, 0x00007239, 
	0x0000944a, 0x0000984c, 0x0000b058, 0x000085cf, 
	0x0000bbd0, 0x0000c5ef, 0x00004faa, 0x0000edfb, 
	0x00008643, 0x00009a4d, 0x00006633, 0x00001185, 
	0x00008a45, 0x0000e9f9, 0x00000402, 0x0000fe7f, 
	0x0000a050, 0x0000783c, 0x0000259f, 0x00004ba8, 
	0x0000a251, 0x00005da3, 0x00008040, 0x0000058f, 
	0x00003f92, 0x0000219d, 0x00007038, 0x0000f1f5, 
	0x000063bc, 0x000077b6, 0x0000afda, 0x00004221, 
	0x00002010, 0x0000e5ff, 0x0000fdf3, 0x0000bfd2, 
	0x000081cd, 0x0000180c, 0x00002613, 0x0000c3ec, 
	0x0000be5f, 0x00003597, 0x00008844, 0x00002e17, 
	0x000093c4, 0x000055a7, 0x0000fc7e, 0x00007a3d, 
	0x0000c864, 0x0000ba5d, 0x00003219, 0x0000e673, 
	0x0000c060, 0x00001981, 0x00009e4f, 0x0000a3dc, 
	0x00004422, 0x0000542a, 0x00003b90, 0x00000b88, 
	0x00008c46, 0x0000c7ee, 0x00006bb8, 0x00002814, 
	0x0000a7de, 0x0000bc5e, 0x0000160b, 0x0000addb, 
	0x0000dbe0, 0x00006432, 0x0000743a, 0x0000140a, 
	0x00009249, 0x00000c06, 0x00004824, 0x0000b85c, 
	0x00009fc2, 0x0000bdd3, 0x000043ac, 0x0000c462, 
	0x00003991, 0x00003195, 0x0000d3e4, 0x0000f279, 
	0x0000d5e7, 0x00008bc8, 0x00006e37, 0x0000da6d, 
	0x0000018d, 0x0000b1d5, 0x00009c4e, 0x000049a9, 
	0x0000d86c, 0x0000ac56, 0x0000f3f4, 0x0000cfea, 
	0x0000ca65, 0x0000f47a, 0x000047ae, 0x00001008, 
	0x00006fba, 0x0000f078, 0x00004a25, 0x00005c2e, 
	0x0000381c, 0x000057a6, 0x000073b4, 0x000097c6, 
	0x0000cbe8, 0x0000a1dd, 0x0000e874, 0x00003e1f, 
	0x0000964b, 0x000061bd, 0x00000d8b, 0x00000f8a, 
	0x0000e070, 0x00007c3e, 0x000071b5, 0x0000cc66, 
	0x00009048, 0x00000603, 0x0000f7f6, 0x00001c0e, 
	0x0000c261, 0x00006a35, 0x0000ae57, 0x000069b9, 
	0x00001786, 0x000099c1, 0x00003a1d, 0x0000279e, 
	0x0000d9e1, 0x0000ebf8, 0x00002b98, 0x00002211, 
	0x0000d269, 0x0000a9d9, 0x0000078e, 0x00003394, 
	0x00002d9b, 0x00003c1e, 0x00001587, 0x0000c9e9, 
	0x000087ce, 0x0000aa55, 0x00005028, 0x0000a5df, 
	0x0000038c, 0x000059a1, 0x00000989, 0x00001a0d, 
	0x000065bf, 0x0000d7e6, 0x00008442, 0x0000d068, 
	0x00008241, 0x00002999, 0x00005a2d, 0x00001e0f, 
	0x00007bb0, 0x0000a854, 0x00006dbb, 0x00002c16
};

static const u32 TBLA3[256]={
	0x000063c6, 0x00007cf8, 0x000077ee, 0x00007bf6, 
	0x0000f2ff, 0x00006bd6, 0x00006fde, 0x0000c591, 
	0x00003060, 0x00000102, 0x000067ce, 0x00002b56, 
	0x0000fee7, 0x0000d7b5, 0x0000ab4d, 0x000076ec, 
	0x0000ca8f, 0x0000821f, 0x0000c989, 0x00007dfa, 
	0x0000faef, 0x000059b2, 0x0000478e, 0x0000f0fb, 
	0x0000ad41, 0x0000d4b3, 0x0000a25f, 0x0000af45, 
	0x00009c23, 0x0000a453, 0x000072e4, 0x0000c09b, 
	0x0000b775, 0x0000fde1, 0x0000933d, 0x0000264c, 
	0x0000366c, 0x00003f7e, 0x0000f7f5, 0x0000cc83, 
	0x00003468, 0x0000a551, 0x0000e5d1, 0x0000f1f9, 
	0x000071e2, 0x0000d8ab, 0x00003162, 0x0000152a, 
	0x00000408, 0x0000c795, 0x00002346, 0x0000c39d, 
	0x00001830, 0x00009637, 0x0000050a, 0x00009a2f, 
	0x0000070e, 0x00001224, 0x0000801b, 0x0000e2df, 
	0x0000ebcd, 0x0000274e, 0x0000b27f, 0x000075ea, 
	0x00000912, 0x0000831d, 0x00002c58, 0x00001a34, 
	0x00001b36, 0x00006edc, 0x00005ab4, 0x0000a05b, 
	0x000052a4, 0x00003b76, 0x0000d6b7, 0x0000b37d, 
	0x00002952, 0x0000e3dd, 0x00002f5e, 0x00008413, 
	0x000053a6, 0x0000d1b9, 0x00000000, 0x0000edc1, 
	0x00002040, 0x0000fce3, 0x0000b179, 0x00005bb6, 
	0x00006ad4, 0x0000cb8d, 0x0000be67, 0x00003972, 
	0x00004a94, 0x00004c98, 0x000058b0, 0x0000cf85, 
	0x0000d0bb, 0x0000efc5, 0x0000aa4f, 0x0000fbed, 
	0x00004386, 0x00004d9a, 0x00003366, 0x00008511, 
	0x0000458a, 0x0000f9e9, 0x00000204, 0x00007ffe, 
	0x000050a0, 0x00003c78, 0x00009f25, 0x0000a84b, 
	0x000051a2, 0x0000a35d, 0x00004080, 0x00008f05, 
	0x0000923f, 0x00009d21, 0x00003870, 0x0000f5f1, 
	0x0000bc63, 0x0000b677, 0x0000daaf, 0x00002142, 
	0x00001020, 0x0000ffe5, 0x0000f3fd, 0x0000d2bf, 
	0x0000cd81, 0x00000c18, 0x00001326, 0x0000ecc3, 
	0x00005fbe, 0x00009735, 0x00004488, 0x0000172e, 
	0x0000c493, 0x0000a755, 0x00007efc, 0x00003d7a, 
	0x000064c8, 0x00005dba, 0x00001932, 0x000073e6, 
	0x000060c0, 0x00008119, 0x00004f9e, 0x0000dca3, 
	0x00002244, 0x00002a54, 0x0000903b, 0x0000880b, 
	0x0000468c, 0x0000eec7, 0x0000b86b, 0x00001428, 
	0x0000dea7, 0x00005ebc, 0x00000b16, 0x0000dbad, 
	0x0000e0db, 0x00003264, 0x00003a74, 0x00000a14, 
	0x00004992, 0x0000060c, 0x00002448, 0x00005cb8, 
	0x0000c29f, 0x0000d3bd, 0x0000ac43, 0x000062c4, 
	0x00009139, 0x00009531, 0x0000e4d3, 0x000079f2, 
	0x0000e7d5, 0x0000c88b, 0x0000376e, 0x00006dda, 
	0x00008d01, 0x0000d5b1, 0x00004e9c, 0x0000a949, 
	0x00006cd8, 0x000056ac, 0x0000f4f3, 0x0000eacf, 
	0x000065ca, 0x00007af4, 0x0000ae47, 0x00000810, 
	0x0000ba6f, 0x000078f0, 0x0000254a, 0x00002e5c, 
	0x00001c38, 0x0000a657, 0x0000b473, 0x0000c697, 
	0x0000e8cb, 0x0000dda1, 0x000074e8, 0x00001f3e, 
	0x00004b96, 0x0000bd61, 0x00008b0d, 0x00008a0f, 
	0x000070e0, 0x00003e7c, 0x0000b571, 0x000066cc, 
	0x00004890, 0x00000306, 0x0000f6f7, 0x00000e1c, 
	0x000061c2, 0x0000356a, 0x000057ae, 0x0000b969, 
	0x00008617, 0x0000c199, 0x00001d3a, 0x00009e27, 
	0x0000e1d9, 0x0000f8eb, 0x0000982b, 0x00001122, 
	0x000069d2, 0x0000d9a9, 0x00008e07, 0x00009433, 
	0x00009b2d, 0x00001e3c, 0x00008715, 0x0000e9c9, 
	0x0000ce87, 0x000055aa, 0x00002850, 0x0000dfa5, 
	0x00008c03, 0x0000a159, 0x00008909, 0x00000d1a, 
	0x0000bf65, 0x0000e6d7, 0x00004284, 0x000068d0, 
	0x00004182, 0x00009929, 0x00002d5a, 0x00000f1e, 
	0x0000b07b, 0x000054a8, 0x0000bb6d, 0x0000162c
};

static const u32 TBLB0[256]={
	0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 
	0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 
	0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 
	0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 
	0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 
	0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 
	0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 
	0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 
	0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 
	0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 
	0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 
	0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 
	0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 
	0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 
	0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 
	0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 
	0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 
	0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 
	0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 
	0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 
	0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 
	0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 
	0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 
	0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 
	0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 
	0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 
	0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 
	0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 
	0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 
	0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 
	0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 
	0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 
	0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 
	0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 
	0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 
	0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 
	0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 
	0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 
	0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 
	0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 
	0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 
	0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 
	0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 
	0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 
	0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 
	0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 
	0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 
	0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 
	0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 
	0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 
	0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 
	0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 
	0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 
	0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 
	0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 
	0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 
	0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 
	0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 
	0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 
	0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 
	0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 
	0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 
	0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 
	0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
};

static const u32 TBLB1[256]={
	0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 
	0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 
	0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 
	0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 
	0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 
	0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 
	0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 
	0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 
	0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 
	0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 
	0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 
	0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 
	0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 
	0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 
	0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 
	0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 
	0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 
	0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 
	0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 
	0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 
	0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 
	0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 
	0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 
	0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 
	0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 
	0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 
	0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 
	0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 
	0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 
	0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 
	0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 
	0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 
	0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 
	0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 
	0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 
	0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 
	0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 
	0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 
	0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 
	0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 
	0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 
	0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 
	0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 
	0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 
	0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 
	0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 
	0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 
	0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 
	0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 
	0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 
	0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 
	0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 
	0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 
	0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 
	0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 
	0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 
	0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 
	0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 
	0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 
	0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 
	0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 
	0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 
	0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 
	0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616
};

static const u32 TBLB2[256]={
	0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 
	0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 
	0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 
	0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 
	0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 
	0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 
	0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 
	0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 
	0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 
	0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 
	0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 
	0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 
	0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 
	0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 
	0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 
	0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 
	0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 
	0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 
	0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 
	0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 
	0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 
	0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 
	0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 
	0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 
	0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 
	0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 
	0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 
	0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 
	0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 
	0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 
	0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 
	0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 
	0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 
	0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 
	0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 
	0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 
	0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 
	0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 
	0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 
	0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 
	0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 
	0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 
	0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 
	0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 
	0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 
	0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 
	0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 
	0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 
	0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 
	0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 
	0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 
	0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 
	0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 
	0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 
	0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 
	0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 
	0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 
	0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 
	0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 
	0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 
	0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 
	0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 
	0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 
	0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16
};

static const u32 TBLB3[256]={
	0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 
	0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 
	0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 
	0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 
	0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 
	0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 
	0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 
	0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 
	0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 
	0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 
	0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 
	0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 
	0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 
	0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 
	0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 
	0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 
	0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 
	0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 
	0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 
	0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 
	0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 
	0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 
	0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 
	0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 
	0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 
	0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 
	0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 
	0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 
	0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 
	0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 
	0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 
	0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 
	0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 
	0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 
	0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 
	0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 
	0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 
	0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 
	0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 
	0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 
	0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 
	0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 
	0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 
	0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 
	0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 
	0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 
	0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 
	0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 
	0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 
	0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 
	0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 
	0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 
	0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 
	0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 
	0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 
	0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 
	0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 
	0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 
	0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 
	0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 
	0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 
	0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 
	0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 
	0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c
};

static const u32 TBLC0[256] = {
	0x63976335, 0x7ceb7ccd, 0x77c77795, 0x7bf77bf5,
	0xf2e5f2d1, 0x6bb76b75, 0x6fa76f55, 0xc539c572,
	0x30c0309b, 0x01040108, 0x67876715, 0x2bac2b43,
	0xfed5feb1, 0xd771d7e2, 0xab9aab2f, 0x76c3769d,
	0xca05ca0a, 0x823e827c, 0xc909c912, 0x7def7dc5,
	0xfac5fa91, 0x597f59fe, 0x4707470e, 0xf0edf0c1,
	0xad82ad1f, 0xd47dd4fa, 0xa2bea267, 0xaf8aaf0f,
	0x9c469c8c, 0xa4a6a457, 0x72d372bd, 0xc02dc05a,
	0xb7eab7cf, 0xfdd9fda9, 0x937a93f4, 0x2698262b,
	0x36d836ab, 0x3ffc3fe3, 0xf7f1f7f9, 0xcc1dcc3a,
	0x34d034bb, 0xa5a2a55f, 0xe5b9e569, 0xf1e9f1c9,
	0x71df71a5, 0xd84dd89a, 0x31c43193, 0x155415a8,
	0x04100420, 0xc731c762, 0x238c2303, 0xc321c342,
	0x186018c0, 0x966e96dc, 0x05140528, 0x9a5e9abc,
	0x071c0738, 0x12481290, 0x8036806c, 0xe2a5e251,
	0xeb81eb19, 0x279c2723, 0xb2feb2e7, 0x75cf7585,
	0x09240948, 0x833a8374, 0x2cb02c7b, 0x1a681ad0,
	0x1b6c1bd8, 0x6ea36e5d, 0x5a735ae6, 0xa0b6a077,
	0x525352a6, 0x3bec3bc3, 0xd675d6ea, 0xb3fab3ef,
	0x29a42953, 0xe3a1e359, 0x2fbc2f63, 0x8426844c,
	0x535753ae, 0xd169d1d2, 0x00000000, 0xed99ed29,
	0x2080201b, 0xfcddfca1, 0xb1f2b1ff, 0x5b775bee,
	0x6ab36a7d, 0xcb01cb02, 0xbecebe87, 0x39e439d3,
	0x4a334a66, 0x4c2b4c56, 0x587b58f6, 0xcf11cf22,
	0xd06dd0da, 0xef91ef39, 0xaa9eaa27, 0xfbc1fb99,
	0x4317432e, 0x4d2f4d5e, 0x33cc3383, 0x85228544,
	0x450f451e, 0xf9c9f989, 0x02080210, 0x7fe77fd5,
	0x505b50b6, 0x3cf03cfb, 0x9f4a9f94, 0xa896a837,
	0x515f51be, 0xa3baa36f, 0x401b4036, 0x8f0a8f14,
	0x927e92fc, 0x9d429d84, 0x38e038db, 0xf5f9f5e9,
	0xbcc6bc97, 0xb6eeb6c7, 0xda45da8a, 0x21842113,
	0x10401080, 0xffd1ffb9, 0xf3e1f3d9, 0xd265d2ca,
	0xcd19cd32, 0x0c300c60, 0x134c1398, 0xec9dec21,
	0x5f675fce, 0x976a97d4, 0x440b4416, 0x175c17b8,
	0xc43dc47a, 0xa7aaa74f, 0x7ee37edd, 0x3df43df3,
	0x648b640d, 0x5d6f5dde, 0x196419c8, 0x73d773b5,
	0x609b602d, 0x81328164, 0x4f274f4e, 0xdc5ddcba,
	0x2288220b, 0x2aa82a4b, 0x907690ec, 0x8816882c,
	0x46034606, 0xee95ee31, 0xb8d6b8b7, 0x145014a0,
	0xde55deaa, 0x5e635ec6, 0x0b2c0b58, 0xdb41db82,
	0xe0ade041, 0x32c8328b, 0x3ae83acb, 0x0a280a50,
	0x493f497e, 0x06180630, 0x2490243b, 0x5c6b5cd6,
	0xc225c24a, 0xd361d3c2, 0xac86ac17, 0x6293623d,
	0x917291e4, 0x956295c4, 0xe4bde461, 0x79ff79e5,
	0xe7b1e779, 0xc80dc81a, 0x37dc37a3, 0x6daf6d45,
	0x8d028d04, 0xd579d5f2, 0x4e234e46, 0xa992a93f,
	0x6cab6c4d, 0x56435686, 0xf4fdf4e1, 0xea85ea11,
	0x658f6505, 0x7af37afd, 0xae8eae07, 0x08200840,
	0xbadebaa7, 0x78fb78ed, 0x25942533, 0x2eb82e6b,
	0x1c701ce0, 0xa6aea647, 0xb4e6b4d7, 0xc635c66a,
	0xe88de801, 0xdd59ddb2, 0x74cb748d, 0x1f7c1ff8,
	0x4b374b6e, 0xbdc2bd9f, 0x8b1a8b34, 0x8a1e8a3c,
	0x70db70ad, 0x3ef83eeb, 0xb5e2b5df, 0x6683661d,
	0x483b4876, 0x030c0318, 0xf6f5f6f1, 0x0e380e70,
	0x619f6125, 0x35d435b3, 0x5747578e, 0xb9d2b9bf,
	0x862e865c, 0xc129c152, 0x1d741de8, 0x9e4e9e9c,
	0xe1a9e149, 0xf8cdf881, 0x985698ac, 0x11441188,
	0x69bf6965, 0xd949d992, 0x8e0e8e1c, 0x946694cc,
	0x9b5a9bb4, 0x1e781ef0, 0x872a8754, 0xe989e909,
	0xce15ce2a, 0x554f559e, 0x28a0285b, 0xdf51dfa2,
	0x8c068c0c, 0xa1b2a17f, 0x89128924, 0x0d340d68,
	0xbfcabf8f, 0xe6b5e671, 0x42134226, 0x68bb686d,
	0x411f413e, 0x995299a4, 0x2db42d73, 0x0f3c0f78,
	0xb0f6b0f7, 0x544b5496, 0xbbdabbaf, 0x165816b0
};

static const u32 TBLC1[256] = {
	0x63639763, 0x7c7ceb7c, 0x7777c777, 0x7b7bf77b,
	0xf2f2e5f2, 0x6b6bb76b, 0x6f6fa76f, 0xc5c539c5,
	0x3030c030, 0x01010401, 0x67678767, 0x2b2bac2b,
	0xfefed5fe, 0xd7d771d7, 0xabab9aab, 0x7676c376,
	0xcaca05ca, 0x82823e82, 0xc9c909c9, 0x7d7def7d,
	0xfafac5fa, 0x59597f59, 0x47470747, 0xf0f0edf0,
	0xadad82ad, 0xd4d47dd4, 0xa2a2bea2, 0xafaf8aaf,
	0x9c9c469c, 0xa4a4a6a4, 0x7272d372, 0xc0c02dc0,
	0xb7b7eab7, 0xfdfdd9fd, 0x93937a93, 0x26269826,
	0x3636d836, 0x3f3ffc3f, 0xf7f7f1f7, 0xcccc1dcc,
	0x3434d034, 0xa5a5a2a5, 0xe5e5b9e5, 0xf1f1e9f1,
	0x7171df71, 0xd8d84dd8, 0x3131c431, 0x15155415,
	0x04041004, 0xc7c731c7, 0x23238c23, 0xc3c321c3,
	0x18186018, 0x96966e96, 0x05051405, 0x9a9a5e9a,
	0x07071c07, 0x12124812, 0x80803680, 0xe2e2a5e2,
	0xebeb81eb, 0x27279c27, 0xb2b2feb2, 0x7575cf75,
	0x09092409, 0x83833a83, 0x2c2cb02c, 0x1a1a681a,
	0x1b1b6c1b, 0x6e6ea36e, 0x5a5a735a, 0xa0a0b6a0,
	0x52525352, 0x3b3bec3b, 0xd6d675d6, 0xb3b3fab3,
	0x2929a429, 0xe3e3a1e3, 0x2f2fbc2f, 0x84842684,
	0x53535753, 0xd1d169d1, 0x00000000, 0xeded99ed,
	0x20208020, 0xfcfcddfc, 0xb1b1f2b1, 0x5b5b775b,
	0x6a6ab36a, 0xcbcb01cb, 0xbebecebe, 0x3939e439,
	0x4a4a334a, 0x4c4c2b4c, 0x58587b58, 0xcfcf11cf,
	0xd0d06dd0, 0xefef91ef, 0xaaaa9eaa, 0xfbfbc1fb,
	0x43431743, 0x4d4d2f4d, 0x3333cc33, 0x85852285,
	0x45450f45, 0xf9f9c9f9, 0x02020802, 0x7f7fe77f,
	0x50505b50, 0x3c3cf03c, 0x9f9f4a9f, 0xa8a896a8,
	0x51515f51, 0xa3a3baa3, 0x40401b40, 0x8f8f0a8f,
	0x92927e92, 0x9d9d429d, 0x3838e038, 0xf5f5f9f5,
	0xbcbcc6bc, 0xb6b6eeb6, 0xdada45da, 0x21218421,
	0x10104010, 0xffffd1ff, 0xf3f3e1f3, 0xd2d265d2,
	0xcdcd19cd, 0x0c0c300c, 0x13134c13, 0xecec9dec,
	0x5f5f675f, 0x97976a97, 0x44440b44, 0x17175c17,
	0xc4c43dc4, 0xa7a7aaa7, 0x7e7ee37e, 0x3d3df43d,
	0x64648b64, 0x5d5d6f5d, 0x19196419, 0x7373d773,
	0x60609b60, 0x81813281, 0x4f4f274f, 0xdcdc5ddc,
	0x22228822, 0x2a2aa82a, 0x90907690, 0x88881688,
	0x46460346, 0xeeee95ee, 0xb8b8d6b8, 0x14145014,
	0xdede55de, 0x5e5e635e, 0x0b0b2c0b, 0xdbdb41db,
	0xe0e0ade0, 0x3232c832, 0x3a3ae83a, 0x0a0a280a,
	0x49493f49, 0x06061806, 0x24249024, 0x5c5c6b5c,
	0xc2c225c2, 0xd3d361d3, 0xacac86ac, 0x62629362,
	0x91917291, 0x95956295, 0xe4e4bde4, 0x7979ff79,
	0xe7e7b1e7, 0xc8c80dc8, 0x3737dc37, 0x6d6daf6d,
	0x8d8d028d, 0xd5d579d5, 0x4e4e234e, 0xa9a992a9,
	0x6c6cab6c, 0x56564356, 0xf4f4fdf4, 0xeaea85ea,
	0x65658f65, 0x7a7af37a, 0xaeae8eae, 0x08082008,
	0xbabadeba, 0x7878fb78, 0x25259425, 0x2e2eb82e,
	0x1c1c701c, 0xa6a6aea6, 0xb4b4e6b4, 0xc6c635c6,
	0xe8e88de8, 0xdddd59dd, 0x7474cb74, 0x1f1f7c1f,
	0x4b4b374b, 0xbdbdc2bd, 0x8b8b1a8b, 0x8a8a1e8a,
	0x7070db70, 0x3e3ef83e, 0xb5b5e2b5, 0x66668366,
	0x48483b48, 0x03030c03, 0xf6f6f5f6, 0x0e0e380e,
	0x61619f61, 0x3535d435, 0x57574757, 0xb9b9d2b9,
	0x86862e86, 0xc1c129c1, 0x1d1d741d, 0x9e9e4e9e,
	0xe1e1a9e1, 0xf8f8cdf8, 0x98985698, 0x11114411,
	0x6969bf69, 0xd9d949d9, 0x8e8e0e8e, 0x94946694,
	0x9b9b5a9b, 0x1e1e781e, 0x87872a87, 0xe9e989e9,
	0xcece15ce, 0x55554f55, 0x2828a028, 0xdfdf51df,
	0x8c8c068c, 0xa1a1b2a1, 0x89891289, 0x0d0d340d,
	0xbfbfcabf, 0xe6e6b5e6, 0x42421342, 0x6868bb68,
	0x41411f41, 0x99995299, 0x2d2db42d, 0x0f0f3c0f,
	0xb0b0f6b0, 0x54544b54, 0xbbbbdabb, 0x16165816
};

static const u32 TBLC2[256] = {
	0xc6636397, 0xf87c7ceb, 0xee7777c7, 0xf67b7bf7,
	0xfff2f2e5, 0xd66b6bb7, 0xde6f6fa7, 0x91c5c539,
	0x603030c0, 0x02010104, 0xce676787, 0x562b2bac,
	0xe7fefed5, 0xb5d7d771, 0x4dabab9a, 0xec7676c3,
	0x8fcaca05, 0x1f82823e, 0x89c9c909, 0xfa7d7def,
	0xeffafac5, 0xb259597f, 0x8e474707, 0xfbf0f0ed,
	0x41adad82, 0xb3d4d47d, 0x5fa2a2be, 0x45afaf8a,
	0x239c9c46, 0x53a4a4a6, 0xe47272d3, 0x9bc0c02d,
	0x75b7b7ea, 0xe1fdfdd9, 0x3d93937a, 0x4c262698,
	0x6c3636d8, 0x7e3f3ffc, 0xf5f7f7f1, 0x83cccc1d,
	0x683434d0, 0x51a5a5a2, 0xd1e5e5b9, 0xf9f1f1e9,
	0xe27171df, 0xabd8d84d, 0x623131c4, 0x2a151554,
	0x08040410, 0x95c7c731, 0x4623238c, 0x9dc3c321,
	0x30181860, 0x3796966e, 0x0a050514, 0x2f9a9a5e,
	0x0e07071c, 0x24121248, 0x1b808036, 0xdfe2e2a5,
	0xcdebeb81, 0x4e27279c, 0x7fb2b2fe, 0xea7575cf,
	0x12090924, 0x1d83833a, 0x582c2cb0, 0x341a1a68,
	0x361b1b6c, 0xdc6e6ea3, 0xb45a5a73, 0x5ba0a0b6,
	0xa4525253, 0x763b3bec, 0xb7d6d675, 0x7db3b3fa,
	0x522929a4, 0xdde3e3a1, 0x5e2f2fbc, 0x13848426,
	0xa6535357, 0xb9d1d169, 0x00000000, 0xc1eded99,
	0x40202080, 0xe3fcfcdd, 0x79b1b1f2, 0xb65b5b77,
	0xd46a6ab3, 0x8dcbcb01, 0x67bebece, 0x723939e4,
	0x944a4a33, 0x984c4c2b, 0xb058587b, 0x85cfcf11,
	0xbbd0d06d, 0xc5efef91, 0x4faaaa9e, 0xedfbfbc1,
	0x86434317, 0x9a4d4d2f, 0x663333cc, 0x11858522,
	0x8a45450f, 0xe9f9f9c9, 0x04020208, 0xfe7f7fe7,
	0xa050505b, 0x783c3cf0, 0x259f9f4a, 0x4ba8a896,
	0xa251515f, 0x5da3a3ba, 0x8040401b, 0x058f8f0a,
	0x3f92927e, 0x219d9d42, 0x703838e0, 0xf1f5f5f9,
	0x63bcbcc6, 0x77b6b6ee, 0xafdada45, 0x42212184,
	0x20101040, 0xe5ffffd1, 0xfdf3f3e1, 0xbfd2d265,
	0x81cdcd19, 0x180c0c30, 0x2613134c, 0xc3ecec9d,
	0xbe5f5f67, 0x3597976a, 0x8844440b, 0x2e17175c,
	0x93c4c43d, 0x55a7a7aa, 0xfc7e7ee3, 0x7a3d3df4,
	0xc864648b, 0xba5d5d6f, 0x32191964, 0xe67373d7,
	0xc060609b, 0x19818132, 0x9e4f4f27, 0xa3dcdc5d,
	0x44222288, 0x542a2aa8, 0x3b909076, 0x0b888816,
	0x8c464603, 0xc7eeee95, 0x6bb8b8d6, 0x28141450,
	0xa7dede55, 0xbc5e5e63, 0x160b0b2c, 0xaddbdb41,
	0xdbe0e0ad, 0x643232c8, 0x743a3ae8, 0x140a0a28,
	0x9249493f, 0x0c060618, 0x48242490, 0xb85c5c6b,
	0x9fc2c225, 0xbdd3d361, 0x43acac86, 0xc4626293,
	0x39919172, 0x31959562, 0xd3e4e4bd, 0xf27979ff,
	0xd5e7e7b1, 0x8bc8c80d, 0x6e3737dc, 0xda6d6daf,
	0x018d8d02, 0xb1d5d579, 0x9c4e4e23, 0x49a9a992,
	0xd86c6cab, 0xac565643, 0xf3f4f4fd, 0xcfeaea85,
	0xca65658f, 0xf47a7af3, 0x47aeae8e, 0x10080820,
	0x6fbabade, 0xf07878fb, 0x4a252594, 0x5c2e2eb8,
	0x381c1c70, 0x57a6a6ae, 0x73b4b4e6, 0x97c6c635,
	0xcbe8e88d, 0xa1dddd59, 0xe87474cb, 0x3e1f1f7c,
	0x964b4b37, 0x61bdbdc2, 0x0d8b8b1a, 0x0f8a8a1e,
	0xe07070db, 0x7c3e3ef8, 0x71b5b5e2, 0xcc666683,
	0x9048483b, 0x0603030c, 0xf7f6f6f5, 0x1c0e0e38,
	0xc261619f, 0x6a3535d4, 0xae575747, 0x69b9b9d2,
	0x1786862e, 0x99c1c129, 0x3a1d1d74, 0x279e9e4e,
	0xd9e1e1a9, 0xebf8f8cd, 0x2b989856, 0x22111144,
	0xd26969bf, 0xa9d9d949, 0x078e8e0e, 0x33949466,
	0x2d9b9b5a, 0x3c1e1e78, 0x1587872a, 0xc9e9e989,
	0x87cece15, 0xaa55554f, 0x502828a0, 0xa5dfdf51,
	0x038c8c06, 0x59a1a1b2, 0x09898912, 0x1a0d0d34,
	0x65bfbfca, 0xd7e6e6b5, 0x84424213, 0xd06868bb,
	0x8241411f, 0x29999952, 0x5a2d2db4, 0x1e0f0f3c,
	0x7bb0b0f6, 0xa854544b, 0x6dbbbbda, 0x2c161658
};

static const u32 TBLC3[256] = {
	0xf3c66363, 0x35f87c7c, 0x7bee7777, 0x03f67b7b,
	0x2efff2f2, 0xa3d66b6b, 0x8bde6f6f, 0xe391c5c5,
	0xfb603030, 0x0a020101, 0xdbce6767, 0x15562b2b,
	0x56e7fefe, 0x57b5d7d7, 0x624dabab, 0x71ec7676,
	0x858fcaca, 0x631f8282, 0x9b89c9c9, 0x3ffa7d7d,
	0x7eeffafa, 0x4cb25959, 0x808e4747, 0x3afbf0f0,
	0x5e41adad, 0x49b3d4d4, 0x385fa2a2, 0x4a45afaf,
	0xaf239c9c, 0x0453a4a4, 0x59e47272, 0xc19bc0c0,
	0xba75b7b7, 0x48e1fdfd, 0xc93d9393, 0x674c2626,
	0xc76c3636, 0x9d7e3f3f, 0x0cf5f7f7, 0xb983cccc,
	0xd3683434, 0x0e51a5a5, 0xb8d1e5e5, 0x30f9f1f1,
	0x47e27171, 0x31abd8d8, 0xf1623131, 0x822a1515,
	0x28080404, 0xf795c7c7, 0x45462323, 0xdf9dc3c3,
	0xf0301818, 0xeb379696, 0x220a0505, 0x932f9a9a,
	0x360e0707, 0xb4241212, 0x771b8080, 0x8edfe2e2,
	0xd4cdebeb, 0x6d4e2727, 0x987fb2b2, 0x6fea7575,
	0x5a120909, 0x691d8383, 0x23582c2c, 0xe4341a1a,
	0xee361b1b, 0x81dc6e6e, 0x52b45a5a, 0x2c5ba0a0,
	0x02a45252, 0xb5763b3b, 0x5db7d6d6, 0x927db3b3,
	0x01522929, 0x84dde3e3, 0x3d5e2f2f, 0x5f138484,
	0x08a65353, 0x6bb9d1d1, 0x00000000, 0xe8c1eded,
	0x5b402020, 0x42e3fcfc, 0x8679b1b1, 0x58b65b5b,
	0xa9d46a6a, 0x8f8dcbcb, 0xe067bebe, 0xa1723939,
	0xf2944a4a, 0xce984c4c, 0x46b05858, 0xa785cfcf,
	0x61bbd0d0, 0xfcc5efef, 0x684faaaa, 0x74edfbfb,
	0xa8864343, 0xc49a4d4d, 0xe5663333, 0x55118585,
	0x948a4545, 0x60e9f9f9, 0x14040202, 0x2bfe7f7f,
	0x16a05050, 0x83783c3c, 0xb1259f9f, 0x7c4ba8a8,
	0x1ca25151, 0x325da3a3, 0xb6804040, 0x11058f8f,
	0xc33f9292, 0xa5219d9d, 0xab703838, 0x18f1f5f5,
	0xf463bcbc, 0xb077b6b6, 0x25afdada, 0x51422121,
	0xa0201010, 0x5ce5ffff, 0x24fdf3f3, 0x75bfd2d2,
	0xb381cdcd, 0x78180c0c, 0xbe261313, 0xe2c3ecec,
	0x70be5f5f, 0xe1359797, 0x9e884444, 0x962e1717,
	0xe993c4c4, 0x1a55a7a7, 0x21fc7e7e, 0x897a3d3d,
	0xc5c86464, 0x64ba5d5d, 0xfa321919, 0x53e67373,
	0xedc06060, 0x7d198181, 0xd09e4f4f, 0x19a3dcdc,
	0x4f442222, 0x1f542a2a, 0xd73b9090, 0x270b8888,
	0x8a8c4646, 0xf6c7eeee, 0xdc6bb8b8, 0x88281414,
	0x0da7dede, 0x7abc5e5e, 0x4e160b0b, 0x2faddbdb,
	0x9adbe0e0, 0xef643232, 0xbf743a3a, 0x44140a0a,
	0xec924949, 0x3c0c0606, 0x73482424, 0x6eb85c5c,
	0xd59fc2c2, 0x7fbdd3d3, 0x5443acac, 0xf9c46262,
	0xdd399191, 0xf5319595, 0xb2d3e4e4, 0x17f27979,
	0xacd5e7e7, 0x918bc8c8, 0xcd6e3737, 0x9fda6d6d,
	0x05018d8d, 0x43b1d5d5, 0xda9c4e4e, 0x7649a9a9,
	0x95d86c6c, 0x2aac5656, 0x12f3f4f4, 0xdecfeaea,
	0xcfca6565, 0x09f47a7a, 0x4047aeae, 0x50100808,
	0xc86fbaba, 0x1df07878, 0x794a2525, 0x375c2e2e,
	0xd8381c1c, 0x1057a6a6, 0xa473b4b4, 0xfd97c6c6,
	0xcacbe8e8, 0x13a1dddd, 0x65e87474, 0xc63e1f1f,
	0xf8964b4b, 0xfe61bdbd, 0x390d8b8b, 0x330f8a8a,
	0x4de07070, 0x977c3e3e, 0xae71b5b5, 0xd1cc6666,
	0xe6904848, 0x1e060303, 0x06f7f6f6, 0x6c1c0e0e,
	0xe7c26161, 0xd96a3535, 0x20ae5757, 0xd669b9b9,
	0x4b178686, 0xcb99c1c1, 0xd23a1d1d, 0xbb279e9e,
	0x90d9e1e1, 0x6aebf8f8, 0x872b9898, 0xaa221111,
	0xb7d26969, 0x3ba9d9d9, 0x1b078e8e, 0xff339494,
	0x992d9b9b, 0xcc3c1e1e, 0x41158787, 0xc0c9e9e9,
	0xad87cece, 0x34aa5555, 0x0b502828, 0x07a5dfdf,
	0x0f038c8c, 0x2659a1a1, 0x2d098989, 0x721a0d0d,
	0xea65bfbf, 0xa6d7e6e6, 0xa2844242, 0xbdd06868,
	0xbc824141, 0x8d299999, 0x295a2d2d, 0x661e0f0f,
	0x8c7bb0b0, 0x3ea85454, 0xc26dbbbb, 0x9c2c1616
};

static const u32 TBLC4[256] = {
	0x56f3c663, 0xb135f87c, 0xe27bee77, 0x8e03f67b,
	0x232efff2, 0x1ea3d66b, 0x3a8bde6f, 0xb7e391c5,
	0xabfb6030, 0x090a0201, 0x72dbce67, 0x6815562b,
	0x4f56e7fe, 0x3557b5d7, 0x84624dab, 0xeb71ec76,
	0xc0858fca, 0xfe631f82, 0xdb9b89c9, 0xb83ffa7d,
	0x6b7eeffa, 0xa74cb259, 0x49808e47, 0x313afbf0,
	0xb25e41ad, 0x2e49b3d4, 0xc5385fa2, 0xa04a45af,
	0x10af239c, 0xf30453a4, 0xcf59e472, 0x9ac19bc0,
	0x78ba75b7, 0x5448e1fd, 0x67c93d93, 0x0d674c26,
	0x9dc76c36, 0xdc9d7e3f, 0x0e0cf5f7, 0xf6b983cc,
	0x8fd36834, 0xfa0e51a5, 0x8cb8d1e5, 0x3830f9f1,
	0xd447e271, 0x4231abd8, 0xa2f16231, 0xbd822a15,
	0x24280804, 0xa5f795c7, 0x20454623, 0x81df9dc3,
	0xd8f03018, 0x4aeb3796, 0x2d220a05, 0x26932f9a,
	0x3f360e07, 0x82b42412, 0xec771b80, 0xb38edfe2,
	0xf2d4cdeb, 0x046d4e27, 0x55987fb2, 0xf06fea75,
	0x415a1209, 0xf7691d83, 0x5723582c, 0xcae4341a,
	0xc3ee361b, 0x3381dc6e, 0xbc52b45a, 0xd72c5ba0,
	0xf402a452, 0xf8b5763b, 0x3c5db7d6, 0x5c927db3,
	0x7a015229, 0xba84dde3, 0x4c3d5e2f, 0xc85f1384,
	0xfd08a653, 0x036bb9d1, 0x00000000, 0xc4e8c1ed,
	0x3b5b4020, 0x5d42e3fc, 0x4e8679b1, 0xb558b65b,
	0x17a9d46a, 0xc98f8dcb, 0x39e067be, 0xeaa17239,
	0x2cf2944a, 0x1ace984c, 0xae46b058, 0xeda785cf,
	0x0a61bbd0, 0xd6fcc5ef, 0x8d684faa, 0x6274edfb,
	0x6da88643, 0x13c49a4d, 0xb0e56633, 0xc1551185,
	0x5b948a45, 0x7060e9f9, 0x12140402, 0xaa2bfe7f,
	0xe616a050, 0xc783783c, 0x0bb1259f, 0x9f7c4ba8,
	0xef1ca251, 0xcc325da3, 0x76b68040, 0x9b11058f,
	0x6ec33f92, 0x19a5219d, 0xe3ab7038, 0x1c18f1f5,
	0x2bf463bc, 0x71b077b6, 0x5025afda, 0x32514221,
	0x90a02010, 0x465ce5ff, 0x2a24fdf3, 0x1875bfd2,
	0xffb381cd, 0x6c78180c, 0x8bbe2613, 0xcde2c3ec,
	0x9170be5f, 0x43e13597, 0x529e8844, 0xaf962e17,
	0xbee993c4, 0xe81a55a7, 0xa321fc7e, 0xce897a3d,
	0x69c5c864, 0x8364ba5d, 0xd1fa3219, 0xc653e673,
	0x4dedc060, 0xe57d1981, 0x01d09e4f, 0x6619a3dc,
	0x294f4422, 0x611f542a, 0x7cd73b90, 0xa4270b88,
	0x408a8c46, 0xdff6c7ee, 0x0fdc6bb8, 0xb4882814,
	0x740da7de, 0x987abc5e, 0x534e160b, 0x592faddb,
	0xa19adbe0, 0xb9ef6432, 0xf1bf743a, 0x5a44140a,
	0x37ec9249, 0x363c0c06, 0x1f734824, 0x8a6eb85c,
	0x88d59fc2, 0x117fbdd3, 0xbb5443ac, 0x5ff9c462,
	0x75dd3991, 0x51f53195, 0x85b2d3e4, 0x9c17f279,
	0x9eacd5e7, 0xd2918bc8, 0x94cd6e37, 0x289fda6d,
	0x8905018d, 0x2743b1d5, 0x08da9c4e, 0x967649a9,
	0x2195d86c, 0xd02aac56, 0x1512f3f4, 0xfbdecfea,
	0x60cfca65, 0x8709f47a, 0xa94047ae, 0x48501008,
	0x1dc86fba, 0x951df078, 0x16794a25, 0x45375c2e,
	0xfcd8381c, 0xe11057a6, 0x63a473b4, 0xacfd97c6,
	0xe9cacbe8, 0x6f13a1dd, 0xf965e874, 0xe7c63e1f,
	0x25f8964b, 0x22fe61bd, 0xbf390d8b, 0xb6330f8a,
	0xdd4de070, 0xd5977c3e, 0x6aae71b5, 0x7bd1cc66,
	0x3ee69048, 0x1b1e0603, 0x0706f7f6, 0x7e6c1c0e,
	0x44e7c261, 0x86d96a35, 0xd920ae57, 0x06d669b9,
	0xda4b1786, 0x93cb99c1, 0xf5d23a1d, 0x02bb279e,
	0xa890d9e1, 0x796aebf8, 0x34872b98, 0x99aa2211,
	0x0cb7d269, 0x4b3ba9d9, 0x921b078e, 0x58ff3394,
	0x2f992d9b, 0xeecc3c1e, 0xd3411587, 0xe0c0c9e9,
	0xe4ad87ce, 0xcb34aa55, 0x730b5028, 0x7d07a5df,
	0x800f038c, 0xde2659a1, 0xad2d0989, 0x65721a0d,
	0x30ea65bf, 0x97a6d7e6, 0x64a28442, 0x05bdd068,
	0x7fbc8241, 0x3d8d2999, 0x5e295a2d, 0x77661e0f,
	0x478c7bb0, 0xc23ea854, 0x14c26dbb, 0xa69c2c16
};

static const u32 TBLC5[256] = {
	0x3556f3c6, 0xcdb135f8, 0x95e27bee, 0xf58e03f6,
	0xd1232eff, 0x751ea3d6, 0x553a8bde, 0x72b7e391,
	0x9babfb60, 0x08090a02, 0x1572dbce, 0x43681556,
	0xb14f56e7, 0xe23557b5, 0x2f84624d, 0x9deb71ec,
	0x0ac0858f, 0x7cfe631f, 0x12db9b89, 0xc5b83ffa,
	0x916b7eef, 0xfea74cb2, 0x0e49808e, 0xc1313afb,
	0x1fb25e41, 0xfa2e49b3, 0x67c5385f, 0x0fa04a45,
	0x8c10af23, 0x57f30453, 0xbdcf59e4, 0x5a9ac19b,
	0xcf78ba75, 0xa95448e1, 0xf467c93d, 0x2b0d674c,
	0xab9dc76c, 0xe3dc9d7e, 0xf90e0cf5, 0x3af6b983,
	0xbb8fd368, 0x5ffa0e51, 0x698cb8d1, 0xc93830f9,
	0xa5d447e2, 0x9a4231ab, 0x93a2f162, 0xa8bd822a,
	0x20242808, 0x62a5f795, 0x03204546, 0x4281df9d,
	0xc0d8f030, 0xdc4aeb37, 0x282d220a, 0xbc26932f,
	0x383f360e, 0x9082b424, 0x6cec771b, 0x51b38edf,
	0x19f2d4cd, 0x23046d4e, 0xe755987f, 0x85f06fea,
	0x48415a12, 0x74f7691d, 0x7b572358, 0xd0cae434,
	0xd8c3ee36, 0x5d3381dc, 0xe6bc52b4, 0x77d72c5b,
	0xa6f402a4, 0xc3f8b576, 0xea3c5db7, 0xef5c927d,
	0x537a0152, 0x59ba84dd, 0x634c3d5e, 0x4cc85f13,
	0xaefd08a6, 0xd2036bb9, 0x00000000, 0x29c4e8c1,
	0x1b3b5b40, 0xa15d42e3, 0xff4e8679, 0xeeb558b6,
	0x7d17a9d4, 0x02c98f8d, 0x8739e067, 0xd3eaa172,
	0x662cf294, 0x561ace98, 0xf6ae46b0, 0x22eda785,
	0xda0a61bb, 0x39d6fcc5, 0x278d684f, 0x996274ed,
	0x2e6da886, 0x5e13c49a, 0x83b0e566, 0x44c15511,
	0x1e5b948a, 0x897060e9, 0x10121404, 0xd5aa2bfe,
	0xb6e616a0, 0xfbc78378, 0x940bb125, 0x379f7c4b,
	0xbeef1ca2, 0x6fcc325d, 0x3676b680, 0x149b1105,
	0xfc6ec33f, 0x8419a521, 0xdbe3ab70, 0xe91c18f1,
	0x972bf463, 0xc771b077, 0x8a5025af, 0x13325142,
	0x8090a020, 0xb9465ce5, 0xd92a24fd, 0xca1875bf,
	0x32ffb381, 0x606c7818, 0x988bbe26, 0x21cde2c3,
	0xce9170be, 0xd443e135, 0x16529e88, 0xb8af962e,
	0x7abee993, 0x4fe81a55, 0xdda321fc, 0xf3ce897a,
	0x0d69c5c8, 0xde8364ba, 0xc8d1fa32, 0xb5c653e6,
	0x2d4dedc0, 0x64e57d19, 0x4e01d09e, 0xba6619a3,
	0x0b294f44, 0x4b611f54, 0xec7cd73b, 0x2ca4270b,
	0x06408a8c, 0x31dff6c7, 0xb70fdc6b, 0xa0b48828,
	0xaa740da7, 0xc6987abc, 0x58534e16, 0x82592fad,
	0x41a19adb, 0x8bb9ef64, 0xcbf1bf74, 0x505a4414,
	0x7e37ec92, 0x30363c0c, 0x3b1f7348, 0xd68a6eb8,
	0x4a88d59f, 0xc2117fbd, 0x17bb5443, 0x3d5ff9c4,
	0xe475dd39, 0xc451f531, 0x6185b2d3, 0xe59c17f2,
	0x799eacd5, 0x1ad2918b, 0xa394cd6e, 0x45289fda,
	0x04890501, 0xf22743b1, 0x4608da9c, 0x3f967649,
	0x4d2195d8, 0x86d02aac, 0xe11512f3, 0x11fbdecf,
	0x0560cfca, 0xfd8709f4, 0x07a94047, 0x40485010,
	0xa71dc86f, 0xed951df0, 0x3316794a, 0x6b45375c,
	0xe0fcd838, 0x47e11057, 0xd763a473, 0x6aacfd97,
	0x01e9cacb, 0xb26f13a1, 0x8df965e8, 0xf8e7c63e,
	0x6e25f896, 0x9f22fe61, 0x34bf390d, 0x3cb6330f,
	0xaddd4de0, 0xebd5977c, 0xdf6aae71, 0x1d7bd1cc,
	0x763ee690, 0x181b1e06, 0xf10706f7, 0x707e6c1c,
	0x2544e7c2, 0xb386d96a, 0x8ed920ae, 0xbf06d669,
	0x5cda4b17, 0x5293cb99, 0xe8f5d23a, 0x9c02bb27,
	0x49a890d9, 0x81796aeb, 0xac34872b, 0x8899aa22,
	0x650cb7d2, 0x924b3ba9, 0x1c921b07, 0xcc58ff33,
	0xb42f992d, 0xf0eecc3c, 0x54d34115, 0x09e0c0c9,
	0x2ae4ad87, 0x9ecb34aa, 0x5b730b50, 0xa27d07a5,
	0x0c800f03, 0x7fde2659, 0x24ad2d09, 0x6865721a,
	0x8f30ea65, 0x7197a6d7, 0x2664a284, 0x6d05bdd0,
	0x3e7fbc82, 0xa43d8d29, 0x735e295a, 0x7877661e,
	0xf7478c7b, 0x96c23ea8, 0xaf14c26d, 0xb0a69c2c
};

static const u32 TBLC6[256] = {
	0x633556f3, 0x7ccdb135, 0x7795e27b, 0x7bf58e03,
	0xf2d1232e, 0x6b751ea3, 0x6f553a8b, 0xc572b7e3,
	0x309babfb, 0x0108090a, 0x671572db, 0x2b436815,
	0xfeb14f56, 0xd7e23557, 0xab2f8462, 0x769deb71,
	0xca0ac085, 0x827cfe63, 0xc912db9b, 0x7dc5b83f,
	0xfa916b7e, 0x59fea74c, 0x470e4980, 0xf0c1313a,
	0xad1fb25e, 0xd4fa2e49, 0xa267c538, 0xaf0fa04a,
	0x9c8c10af, 0xa457f304, 0x72bdcf59, 0xc05a9ac1,
	0xb7cf78ba, 0xfda95448, 0x93f467c9, 0x262b0d67,
	0x36ab9dc7, 0x3fe3dc9d, 0xf7f90e0c, 0xcc3af6b9,
	0x34bb8fd3, 0xa55ffa0e, 0xe5698cb8, 0xf1c93830,
	0x71a5d447, 0xd89a4231, 0x3193a2f1, 0x15a8bd82,
	0x04202428, 0xc762a5f7, 0x23032045, 0xc34281df,
	0x18c0d8f0, 0x96dc4aeb, 0x05282d22, 0x9abc2693,
	0x07383f36, 0x129082b4, 0x806cec77, 0xe251b38e,
	0xeb19f2d4, 0x2723046d, 0xb2e75598, 0x7585f06f,
	0x0948415a, 0x8374f769, 0x2c7b5723, 0x1ad0cae4,
	0x1bd8c3ee, 0x6e5d3381, 0x5ae6bc52, 0xa077d72c,
	0x52a6f402, 0x3bc3f8b5, 0xd6ea3c5d, 0xb3ef5c92,
	0x29537a01, 0xe359ba84, 0x2f634c3d, 0x844cc85f,
	0x53aefd08, 0xd1d2036b, 0x00000000, 0xed29c4e8,
	0x201b3b5b, 0xfca15d42, 0xb1ff4e86, 0x5beeb558,
	0x6a7d17a9, 0xcb02c98f, 0xbe8739e0, 0x39d3eaa1,
	0x4a662cf2, 0x4c561ace, 0x58f6ae46, 0xcf22eda7,
	0xd0da0a61, 0xef39d6fc, 0xaa278d68, 0xfb996274,
	0x432e6da8, 0x4d5e13c4, 0x3383b0e5, 0x8544c155,
	0x451e5b94, 0xf9897060, 0x02101214, 0x7fd5aa2b,
	0x50b6e616, 0x3cfbc783, 0x9f940bb1, 0xa8379f7c,
	0x51beef1c, 0xa36fcc32, 0x403676b6, 0x8f149b11,
	0x92fc6ec3, 0x9d8419a5, 0x38dbe3ab, 0xf5e91c18,
	0xbc972bf4, 0xb6c771b0, 0xda8a5025, 0x21133251,
	0x108090a0, 0xffb9465c, 0xf3d92a24, 0xd2ca1875,
	0xcd32ffb3, 0x0c606c78, 0x13988bbe, 0xec21cde2,
	0x5fce9170, 0x97d443e1, 0x4416529e, 0x17b8af96,
	0xc47abee9, 0xa74fe81a, 0x7edda321, 0x3df3ce89,
	0x640d69c5, 0x5dde8364, 0x19c8d1fa, 0x73b5c653,
	0x602d4ded, 0x8164e57d, 0x4f4e01d0, 0xdcba6619,
	0x220b294f, 0x2a4b611f, 0x90ec7cd7, 0x882ca427,
	0x4606408a, 0xee31dff6, 0xb8b70fdc, 0x14a0b488,
	0xdeaa740d, 0x5ec6987a, 0x0b58534e, 0xdb82592f,
	0xe041a19a, 0x328bb9ef, 0x3acbf1bf, 0x0a505a44,
	0x497e37ec, 0x0630363c, 0x243b1f73, 0x5cd68a6e,
	0xc24a88d5, 0xd3c2117f, 0xac17bb54, 0x623d5ff9,
	0x91e475dd, 0x95c451f5, 0xe46185b2, 0x79e59c17,
	0xe7799eac, 0xc81ad291, 0x37a394cd, 0x6d45289f,
	0x8d048905, 0xd5f22743, 0x4e4608da, 0xa93f9676,
	0x6c4d2195, 0x5686d02a, 0xf4e11512, 0xea11fbde,
	0x650560cf, 0x7afd8709, 0xae07a940, 0x08404850,
	0xbaa71dc8, 0x78ed951d, 0x25331679, 0x2e6b4537,
	0x1ce0fcd8, 0xa647e110, 0xb4d763a4, 0xc66aacfd,
	0xe801e9ca, 0xddb26f13, 0x748df965, 0x1ff8e7c6,
	0x4b6e25f8, 0xbd9f22fe, 0x8b34bf39, 0x8a3cb633,
	0x70addd4d, 0x3eebd597, 0xb5df6aae, 0x661d7bd1,
	0x48763ee6, 0x03181b1e, 0xf6f10706, 0x0e707e6c,
	0x612544e7, 0x35b386d9, 0x578ed920, 0xb9bf06d6,
	0x865cda4b, 0xc15293cb, 0x1de8f5d2, 0x9e9c02bb,
	0xe149a890, 0xf881796a, 0x98ac3487, 0x118899aa,
	0x69650cb7, 0xd9924b3b, 0x8e1c921b, 0x94cc58ff,
	0x9bb42f99, 0x1ef0eecc, 0x8754d341, 0xe909e0c0,
	0xce2ae4ad, 0x559ecb34, 0x285b730b, 0xdfa27d07,
	0x8c0c800f, 0xa17fde26, 0x8924ad2d, 0x0d686572,
	0xbf8f30ea, 0xe67197a6, 0x422664a2, 0x686d05bd,
	0x413e7fbc, 0x99a43d8d, 0x2d735e29, 0x0f787766,
	0xb0f7478c, 0x5496c23e, 0xbbaf14c2, 0x16b0a69c
};

static const u32 TBLC7[256] = {
	0x97633556, 0xeb7ccdb1, 0xc77795e2, 0xf77bf58e,
	0xe5f2d123, 0xb76b751e, 0xa76f553a, 0x39c572b7,
	0xc0309bab, 0x04010809, 0x87671572, 0xac2b4368,
	0xd5feb14f, 0x71d7e235, 0x9aab2f84, 0xc3769deb,
	0x05ca0ac0, 0x3e827cfe, 0x09c912db, 0xef7dc5b8,
	0xc5fa916b, 0x7f59fea7, 0x07470e49, 0xedf0c131,
	0x82ad1fb2, 0x7dd4fa2e, 0xbea267c5, 0x8aaf0fa0,
	0x469c8c10, 0xa6a457f3, 0xd372bdcf, 0x2dc05a9a,
	0xeab7cf78, 0xd9fda954, 0x7a93f467, 0x98262b0d,
	0xd836ab9d, 0xfc3fe3dc, 0xf1f7f90e, 0x1dcc3af6,
	0xd034bb8f, 0xa2a55ffa, 0xb9e5698c, 0xe9f1c938,
	0xdf71a5d4, 0x4dd89a42, 0xc43193a2, 0x5415a8bd,
	0x10042024, 0x31c762a5, 0x8c230320, 0x21c34281,
	0x6018c0d8, 0x6e96dc4a, 0x1405282d, 0x5e9abc26,
	0x1c07383f, 0x48129082, 0x36806cec, 0xa5e251b3,
	0x81eb19f2, 0x9c272304, 0xfeb2e755, 0xcf7585f0,
	0x24094841, 0x3a8374f7, 0xb02c7b57, 0x681ad0ca,
	0x6c1bd8c3, 0xa36e5d33, 0x735ae6bc, 0xb6a077d7,
	0x5352a6f4, 0xec3bc3f8, 0x75d6ea3c, 0xfab3ef5c,
	0xa429537a, 0xa1e359ba, 0xbc2f634c, 0x26844cc8,
	0x5753aefd, 0x69d1d203, 0x00000000, 0x99ed29c4,
	0x80201b3b, 0xddfca15d, 0xf2b1ff4e, 0x775beeb5,
	0xb36a7d17, 0x01cb02c9, 0xcebe8739, 0xe439d3ea,
	0x334a662c, 0x2b4c561a, 0x7b58f6ae, 0x11cf22ed,
	0x6dd0da0a, 0x91ef39d6, 0x9eaa278d, 0xc1fb9962,
	0x17432e6d, 0x2f4d5e13, 0xcc3383b0, 0x228544c1,
	0x0f451e5b, 0xc9f98970, 0x08021012, 0xe77fd5aa,
	0x5b50b6e6, 0xf03cfbc7, 0x4a9f940b, 0x96a8379f,
	0x5f51beef, 0xbaa36fcc, 0x1b403676, 0x0a8f149b,
	0x7e92fc6e, 0x429d8419, 0xe038dbe3, 0xf9f5e91c,
	0xc6bc972b, 0xeeb6c771, 0x45da8a50, 0x84211332,
	0x40108090, 0xd1ffb946, 0xe1f3d92a, 0x65d2ca18,
	0x19cd32ff, 0x300c606c, 0x4c13988b, 0x9dec21cd,
	0x675fce91, 0x6a97d443, 0x0b441652, 0x5c17b8af,
	0x3dc47abe, 0xaaa74fe8, 0xe37edda3, 0xf43df3ce,
	0x8b640d69, 0x6f5dde83, 0x6419c8d1, 0xd773b5c6,
	0x9b602d4d, 0x328164e5, 0x274f4e01, 0x5ddcba66,
	0x88220b29, 0xa82a4b61, 0x7690ec7c, 0x16882ca4,
	0x03460640, 0x95ee31df, 0xd6b8b70f, 0x5014a0b4,
	0x55deaa74, 0x635ec698, 0x2c0b5853, 0x41db8259,
	0xade041a1, 0xc8328bb9, 0xe83acbf1, 0x280a505a,
	0x3f497e37, 0x18063036, 0x90243b1f, 0x6b5cd68a,
	0x25c24a88, 0x61d3c211, 0x86ac17bb, 0x93623d5f,
	0x7291e475, 0x6295c451, 0xbde46185, 0xff79e59c,
	0xb1e7799e, 0x0dc81ad2, 0xdc37a394, 0xaf6d4528,
	0x028d0489, 0x79d5f227, 0x234e4608, 0x92a93f96,
	0xab6c4d21, 0x435686d0, 0xfdf4e115, 0x85ea11fb,
	0x8f650560, 0xf37afd87, 0x8eae07a9, 0x20084048,
	0xdebaa71d, 0xfb78ed95, 0x94253316, 0xb82e6b45,
	0x701ce0fc, 0xaea647e1, 0xe6b4d763, 0x35c66aac,
	0x8de801e9, 0x59ddb26f, 0xcb748df9, 0x7c1ff8e7,
	0x374b6e25, 0xc2bd9f22, 0x1a8b34bf, 0x1e8a3cb6,
	0xdb70addd, 0xf83eebd5, 0xe2b5df6a, 0x83661d7b,
	0x3b48763e, 0x0c03181b, 0xf5f6f107, 0x380e707e,
	0x9f612544, 0xd435b386, 0x47578ed9, 0xd2b9bf06,
	0x2e865cda, 0x29c15293, 0x741de8f5, 0x4e9e9c02,
	0xa9e149a8, 0xcdf88179, 0x5698ac34, 0x44118899,
	0xbf69650c, 0x49d9924b, 0x0e8e1c92, 0x6694cc58,
	0x5a9bb42f, 0x781ef0ee, 0x2a8754d3, 0x89e909e0,
	0x15ce2ae4, 0x4f559ecb, 0xa0285b73, 0x51dfa27d,
	0x068c0c80, 0xb2a17fde, 0x128924ad, 0x340d6865,
	0xcabf8f30, 0xb5e67197, 0x13422664, 0xbb686d05,
	0x1f413e7f, 0x5299a43d, 0xb42d735e, 0x3c0f7877,
	0xf6b0f747, 0x4b5496c2, 0xdabbaf14, 0x5816b0a6
};

static const u8 CNS[32][2] = {
    {0x01, 0x00}, {0x03, 0x02}, 
    {0x05, 0x04}, {0x07, 0x06},
    {0x09, 0x08}, {0x0b, 0x0a}, 
    {0x0d, 0x0c}, {0x0f, 0x0e},
    {0x11, 0x10}, {0x13, 0x12}, 
    {0x15, 0x14}, {0x17, 0x16},
    {0x19, 0x18}, {0x1b, 0x1a}, 
    {0x1d, 0x1c}, {0x1f, 0x1e},
    {0x21, 0x20}, {0x23, 0x22}, 
    {0x25, 0x24}, {0x27, 0x26},
    {0x29, 0x28}, {0x2b, 0x2a}, 
    {0x2d, 0x2c}, {0x2f, 0x2e},
    {0x31, 0x30}, {0x33, 0x32}, 
    {0x35, 0x34}, {0x37, 0x36},
    {0x39, 0x38}, {0x3b, 0x3a}, 
    {0x3d, 0x3c}, {0x3f, 0x3e}
};

HashReturn Init256(hashState *state)
{
	ST256(state).bitlen[0] = 0;
	ST256(state).bitlen[1] = 0;

	ST256(state).rembitlen = 0;

	memset(ST256(state).buffer, 0, sizeof(ST256(state).buffer));
	memcpy(ST256(state).hash, H_init256, sizeof(ST256(state).hash));

	return SUCCESS;
}

HashReturn Update256(hashState *state, const BitSequence *data, Datalength databitlen)
{
	u8 *p = (u8*)ST256(state).buffer;
	u32 cpylen;
	u32 len;

	if ((ST256(state).bitlen[1] += (u32)databitlen) < (u32)databitlen) {
		ST256(state).bitlen[0] +=1;
	}
	ST256(state).bitlen[0] += (u32)(databitlen >> 32);

	if (ST256(state).rembitlen + databitlen >= LESAMNTA256_BLOCK_BIT_LEN) {
		cpylen = LESAMNTA256_BLOCK_LEN - (ST256(state).rembitlen >> 3);

		memcpy(p + (ST256(state).rembitlen >> 3), data, cpylen);

		BYTES_SWAP256(ST256(state).buffer);

		Compression256(ST256(state).hash, ST256(state).buffer);

		databitlen -= (cpylen << 3);
		data += cpylen;
		ST256(state).rembitlen = 0;

		while (databitlen >= LESAMNTA256_BLOCK_BIT_LEN) {
			memcpy(p, data, LESAMNTA256_BLOCK_LEN);

			BYTES_SWAP256(ST256(state).buffer);

			Compression256(ST256(state).hash, ST256(state).buffer);

			databitlen -= LESAMNTA256_BLOCK_BIT_LEN;
			data += LESAMNTA256_BLOCK_LEN;
		}
	}

	/* All remaining data copy to buffer */
	if (databitlen) {
		len = databitlen >> 3;
		if (databitlen % 8 != 0) {
			len += 1;
		}

		memcpy(p + (ST256(state).rembitlen >> 3), data, len);
		ST256(state).rembitlen += databitlen;
	}

	return SUCCESS;
}

HashReturn Final256(hashState *state, BitSequence *hashval)
{
	u8 *p = (u8*)ST256(state).buffer;
	int bytePos;
	int bitPos;

	/* Get the byte position in which padding is needed */
	bytePos = ST256(state).rembitlen >> 3;

	/* Get the bit position in which last 1-bit data is stored */
	bitPos = (ST256(state).rembitlen % 8);

	if (bitPos == 0) {
		/* Concatenate with a single 1 bit and zero bits */
		p[bytePos] = 0x80;
	} else {
		/* Mask for the upper n bits (n = bitPos) */
		p[bytePos] &= (0xff << (8 - bitPos));

		/* Concatenate with a single 1 bit and zero bits */
		p[bytePos] |= (0x80 >> bitPos);
	}

	/* Concatenate with zero bits */
	memset(&p[bytePos + 1], 0, LESAMNTA256_BLOCK_LEN - (bytePos + 1));

	/* If data bit length is not a multiple of 256 bits */
	if (ST256(state).rembitlen != 0) {
		BYTES_SWAP256(ST256(state).buffer);

		Compression256(ST256(state).hash, ST256(state).buffer);

		memset(p, 0, LESAMNTA256_BLOCK_LEN);
	}

	BYTES_SWAP256(ST256(state).buffer);

	/* Store the data bit length in lower 64 bits of a 256-bit data block */
	ST256(state).buffer[6] = ST256(state).bitlen[0];
	ST256(state).buffer[7] = ST256(state).bitlen[1];

	Output256(ST256(state).hash, ST256(state).buffer);

	BYTES_SWAP256(ST256(state).hash);

	memcpy(hashval, &ST256(state).hash, state->hashbitlen >> 3);

	return SUCCESS;
}

HashReturn Init512(hashState *state)
{
	ST512(state).bitlen[0] = 0;
	ST512(state).bitlen[1] = 0;
	ST512(state).bitlen[2] = 0;
	ST512(state).bitlen[3] = 0;

	ST512(state).rembitlen = 0;

	memset(ST512(state).buffer, 0, sizeof(ST512(state).buffer));
	memcpy(ST512(state).hash, H_init512, sizeof(ST512(state).hash));

	return SUCCESS;
}

HashReturn Update512(hashState *state, const BitSequence *data, Datalength databitlen)
{
	u8 *p =(u8*) ST512(state).buffer;
	u32 cpylen;
	u32 len;
	u32 carry[3];

	carry[0] = carry[1] = carry[2] = 0;

	if ((ST512(state).bitlen[3] += (u32)databitlen) < (u32)databitlen) {
		carry[2]++;
	}
	if ((ST512(state).bitlen[2] += (u32)(databitlen >> 32)) < (u32)(databitlen >> 32)) {
		carry[1]++;
	}
	if ((ST512(state).bitlen[2] += carry[2]) < carry[2]) {
		carry[1]++;
	}
	if ((ST512(state).bitlen[1] += carry[1]) < carry[1]) {
		carry[0]++;
	}
	ST512(state).bitlen[0] += carry[0];

	if ( ST512(state).rembitlen + databitlen >= LESAMNTA512_BLOCK_BIT_LEN) {
		cpylen = LESAMNTA512_BLOCK_LEN - (ST512(state).rembitlen >> 3);

		memcpy(p + (ST512(state).rembitlen >> 3), data, cpylen);

		BYTES_SWAP512(ST512(state).buffer);

		Compression512(ST512(state).hash, ST512(state).buffer);

		databitlen -= (cpylen << 3);
		data += cpylen;
		ST512(state).rembitlen = 0;

		while (databitlen >= LESAMNTA512_BLOCK_BIT_LEN) {
			memcpy(p, data, LESAMNTA512_BLOCK_LEN);

			BYTES_SWAP512(ST512(state).buffer);

			Compression512(ST512(state).hash, ST512(state).buffer);

			databitlen -= LESAMNTA512_BLOCK_BIT_LEN;
			data += LESAMNTA512_BLOCK_LEN;
		}
	}

	/* All remaining data copy to buffer */
	if (databitlen) {
		len = databitlen >> 3;
		if (databitlen % 8 != 0) {
			len += 1;
		}

		memcpy(p + (ST512(state).rembitlen >> 3), data, len);
		ST512(state).rembitlen += databitlen;
	}

	return SUCCESS;
}

HashReturn Final512(hashState *state, BitSequence *hashval)
{
	u8 *p = (u8*)ST512(state).buffer;
	int bytePos;
	int bitPos;

	/* Get the byte position in which padding is needed */
	bytePos = (ST512(state).rembitlen) >> 3;

	/* Get the bit position in which last 1-bit data is stored */
	bitPos = ST512(state).rembitlen % 8;

	if (bitPos == 0) {
		/* Concatenate with a single 1 bit and zero bits */
		p[bytePos] = 0x80;
	} else {
		/* Mask for the upper n bits (n = bitPos) */
		p[bytePos] &= (0xff << (8 - bitPos));

		/* Concatenate with a single 1 bit and zero bits */
		p[bytePos] |= (0x80 >> bitPos);
	}

	/* Concatenate with zero bits */
	memset(&p[bytePos + 1], 0, LESAMNTA512_BLOCK_LEN - (bytePos + 1));

	/* If data bit length is not a multiple of 512 bits */
	if (ST512(state).rembitlen != 0) {
		BYTES_SWAP512(ST512(state).buffer);

		Compression512(ST512(state).hash, ST512(state).buffer);

		memset(p, 0, LESAMNTA512_BLOCK_LEN);
	}       

	BYTES_SWAP512(ST512(state).buffer);

	/* Store the data bit length in lower 128 bits of a 512-bit data block */
	ST512(state).buffer[12] = ST512(state).bitlen[0];
	ST512(state).buffer[13] = ST512(state).bitlen[1];
	ST512(state).buffer[14] = ST512(state).bitlen[2];
	ST512(state).buffer[15] = ST512(state).bitlen[3];

	Output512(ST512(state).hash, ST512(state).buffer);

	BYTES_SWAP512(ST512(state).hash);

	memcpy(hashval, &ST512(state).hash, state->hashbitlen >> 3);

	return SUCCESS;
}

HashReturn Init224(hashState *state)
{
	ST224(state).bitlen[0] = 0;
	ST224(state).bitlen[1] = 0;

	ST224(state).rembitlen = 0;

	memset(ST224(state).buffer, 0, sizeof(ST224(state).buffer));
	memcpy(ST224(state).hash, H_init224, sizeof(ST224(state).hash));

	return SUCCESS;
}

HashReturn Update224(hashState *state, const BitSequence *data, Datalength databitlen)
{
	return  Update256(state, data, databitlen); 
}

HashReturn Final224(hashState *state, BitSequence *hashval) 
{
	return  Final256(state, hashval); 
}

HashReturn Init384(hashState *state)
{
	ST384(state).bitlen[0] = 0;
	ST384(state).bitlen[1] = 0;
	ST384(state).bitlen[2] = 0;
	ST384(state).bitlen[3] = 0;

	ST384(state).rembitlen = 0;

	memset(ST384(state).buffer, 0, sizeof(ST384(state).buffer));
	memcpy(ST384(state).hash, H_init384, sizeof(ST384(state).hash));

	return SUCCESS;
}

HashReturn Update384(hashState *state, const BitSequence *data, Datalength databitlen)
{
	return  Update512(state, data, databitlen); 
}

HashReturn Final384(hashState *state, BitSequence *hashval) 
{
	return  Final512(state, hashval); 
}

HashReturn Hash(int hashbitlen, const BitSequence *data, Datalength databitlen, BitSequence *hashval) 
{
	hashState state;
	HashReturn ret;

	ret = Init(&state, hashbitlen);
	if (ret != SUCCESS) {
		return ret;
	}

	ret = Update(&state, data, databitlen);
	if (ret != SUCCESS) {
		return ret;
	}

	ret = Final(&state, hashval);
	if (ret != SUCCESS) {
		return ret;
	}
	return SUCCESS;
}

HashReturn Init(hashState *state, int hashbitlen) 
{
	HashReturn ret = FAIL;

	state->hashbitlen = hashbitlen;

	switch(hashbitlen) {
		case LESAMNTA224_DIGEST_BIT_LEN:
			ret = Init224(state);
			break;
		case LESAMNTA256_DIGEST_BIT_LEN:
			ret = Init256(state);
			break;
		case LESAMNTA384_DIGEST_BIT_LEN:
			ret = Init384(state);
			break;
		case LESAMNTA512_DIGEST_BIT_LEN:
			ret = Init512(state);
			break;
		default:
			ret = BAD_HASHBITLEN;
			break;
	}

	return ret;
}

HashReturn Update(hashState *state, const BitSequence *data, Datalength databitlen) 
{
	HashReturn ret = FAIL;

	switch(state->hashbitlen) {
		case LESAMNTA224_DIGEST_BIT_LEN:
			ret = Update224(state, data, databitlen);
			break;
		case LESAMNTA256_DIGEST_BIT_LEN:
			ret = Update256(state, data, databitlen);
			break;
		case LESAMNTA384_DIGEST_BIT_LEN:
			ret = Update384(state, data, databitlen);
			break;
		case LESAMNTA512_DIGEST_BIT_LEN:
			ret = Update512(state, data, databitlen);
			break;
		default:
			ret = BAD_HASHBITLEN;
			break;
	}

	return ret;
}

HashReturn Final(hashState *state, BitSequence *hashval) 
{
	HashReturn ret = FAIL;

	switch(state->hashbitlen) {
		case LESAMNTA224_DIGEST_BIT_LEN:
			ret = Final224(state, hashval);
			break;
		case LESAMNTA256_DIGEST_BIT_LEN:
			ret = Final256(state, hashval);
			break;
		case LESAMNTA384_DIGEST_BIT_LEN:
			ret = Final384(state, hashval);
			break;
		case LESAMNTA512_DIGEST_BIT_LEN:
			ret = Final512(state, hashval);
			break;
		default:
			ret = BAD_HASHBITLEN;
			break;
	}

	return ret;
}

static void Compression256(u32 *H, const u32 *M) 
{
	int i;
	u32 midkey[8], midmsg[8];
	struct {
		u32 key[2];
		u32 msg[2];
		u32 t[2];
	} tmp;

	for (i = 0; i < 8; i++) {
		midkey[i] = H[i];
		midmsg[i] = M[i];
	}

	for (i = 0; i < 8; i++) {
		ROUND256(4, 0, 6, 4 * i);
		ROUND256(2, 6, 4, 4 * i + 1);
		ROUND256(0, 4, 2, 4 * i + 2);
		ROUND256(6, 2, 0, 4 * i + 3);
	}

	for (i = 0; i < 8; i++) {
		H[i] = M[i] ^ midmsg[i];
	}
}

static void Output256(u32 *H, const u32 *M) 
{
	int i;
	u32 midkey[8], midmsg[8];
	struct {
		u32 key[2];
		u32 msg[2];
		u32 t[2];
	} tmp;

	for (i = 0; i < 8; i++) {
		midkey[i] = H[i];
		midmsg[i] = M[i];
	}

	for (i = 0; i < 8; i++) {
		ROUND256_OUTPUT(4, 0, 6, 4 * i);
		ROUND256_OUTPUT(2, 6, 4, 4 * i + 1);
		ROUND256_OUTPUT(0, 4, 2, 4 * i + 2);
		ROUND256_OUTPUT(6, 2, 0, 4 * i + 3);
	}

	for (i = 0; i < 8; i++) {
		H[i] = M[i] ^ midmsg[i];
	}
}

static void Compression512(u32 *H, const u32 *M)
{
	int i;
	u32 midkey[16], midmsg[16];
	struct {
		u32 key[4];
		u32 msg[4];
		u32 t[4];
	} tmp;

	for (i = 0; i < 16; i++) {
		midkey[i] = H[i];
		midmsg[i] = M[i];
	}

	for (i = 0; i < 8; i++) {
		ROUND512( 8,  0, 12, 4 * i);
		ROUND512( 4, 12,  8, 4 * i + 1);
		ROUND512( 0,  8,  4, 4 * i + 2);
		ROUND512(12,  4,  0, 4 * i + 3);
	}

	for (i = 0; i < 16; i++) {
		H[i] = M[i] ^ midmsg[i];
	}
}

static void Output512(u32 *H, const u32 *M) 
{
	int i;
	u32 midkey[16], midmsg[16];
	struct {
		u32 key[4];
		u32 msg[4];
		u32 t[4];
	} tmp;

	for (i = 0; i < 16; i++) {
		midkey[i] = H[i];
		midmsg[i] = M[i];
	}

	for (i = 0; i < 8; i++) {
		ROUND512_OUTPUT( 8,  0, 12, 4 * i);
		ROUND512_OUTPUT( 4, 12,  8, 4 * i + 1);
		ROUND512_OUTPUT( 0,  8,  4, 4 * i + 2);
		ROUND512_OUTPUT(12,  4,  0, 4 * i + 3);
	}

	for (i = 0; i < 16; i++) {
		H[i] = M[i] ^ midmsg[i];
	}
}

